IIC读取:SDA_in SDA_out的意思

IIC读取语句里的语句:
uchar DAC5571_check(void)
{
        uchar slaveack;
        SDA_in;                       
        SCL_H;                     
        I2C_delay();                  
        slaveack = SDA_read ;         
        SCL_L;                     
        I2C_delay();                  
        SDA_out;                    
        if(slaveack)    return 0;       
        else            return 1;  
}    
其中的两条语句的解析:
#define SDA_in  {GPIOB->MODER&=~(3<<(11*2));GPIOB->MODER|=0<<11*2;}    
#define SDA_out {GPIOB->MODER&=~(3<<(11*2));GPIOB->MODER|=1<<11*2;}

语句的意思是:~(3<<(11*2)) :相当于11左移22位,也就是22和23位都是1,再取反就是00,GPIOB->MODER和22、23位(00)取与运算,则为00,同理00左移22位再和GPIOB->MODER取或运算(不变);
对应下表的指示00代表 输入复位状态。
#define SDA_out {GPIOB->MODER&=~(3<<(11*2));GPIOB->MODER|=1<<11*2;}
前面的一句和上面的分析一样不变,关键是后一句GPIOB->MODER|=1<<11*2,01左移22位,表示22为1,23位为0,再取或则22位为1,23位保持不变即是为0;显然对应下面的通用输出模式。
因为我们的器件作为从机 要读取从机的地址故数据方向为从机到MCU的传输,所以IO口作为输入,同时用完以后恢复输出模式。

寄存器在STM32F4中文参考手册里的定义是:


//#include "system/init.h" #include "asm/iic_soft.h" #include "generic/gpio.h" #define IIC_SCL_DIR(scl, val) \ gpio_set_direction(scl, val) //设置输入输出模式val 1:输入;0:输出 #define IIC_SCL_SET_PU(scl, on) \ gpio_set_pull_up(scl, on) //on 1:上拉电阻;0:不上拉电阻 #define IIC_SCL_SET_PD(scl, on) \ gpio_set_pull_down(scl, on) //on 1:下拉电阻;0:不下拉电阻 #define IIC_SCL_SET_DIE(scl, on) \ gpio_set_die(scl, on) //on 1:IO普通输出;0:IO模拟输入 #define IIC_SCL_H(scl) \ gpio_set_direction(scl, 1) //引脚输出高电平 #define IIC_SCL_L(scl) \ gpio_direction_output(scl, 0) //引脚输出低电平 //------------------------------------------------------ #define IIC_SDA_DIR(sda, val) \ gpio_set_direction(sda, val) //设置输入输出模式val 1:输入;0:输出 #define IIC_SDA_SET_PU(sda, on) \ gpio_set_pull_up(sda, on) //on 1:上拉电阻;0:不上拉电阻 #define IIC_SDA_SET_PD(sda, on) \ gpio_set_pull_down(sda, on) //on 1:下拉电阻;0:不下拉电阻 #define IIC_SDA_SET_DIE(sda, on) \ gpio_set_die(sda, on) //on 1:IO普通输出;0:IO模拟输入 #define IIC_SDA_H(sda) \ gpio_set_direction(sda, 1) //引脚输出高电平 #define IIC_SDA_L(sda) \ gpio_direction_output(sda, 0) //引脚输出低电平 #define IIC_SDA_READ(sda) \ gpio_read(sda) //读取当前引脚的电平;1:高电平;0:低电平 //------------------------------------------------------- #define iic_get_id(iic) (iic) //iic_get_id(iic)等价于iic //------------------------------------------------------- /* 定义在板级.c文件中 const struct soft_iic_config soft_iic_cfg[] = { //iic0 data { .scl = TCFG_SW_I2C0_CLK_PORT, //IIC CLK脚 .sda = TCFG_SW_I2C0_DAT_PORT, //IIC DAT脚 .delay = 50, //软件IIC延时参数,影响通讯时钟频率 .io_pu = 0,//1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 }, }; 即soft_iic_dev iiciic的值只能为0 */ static inline u32 iic_get_scl(soft_iic_dev iic) { u8 id = iic_get_id(iic); return soft_iic_cfg[id].scl; } static inline u32 iic_get_sda(soft_iic_dev iic) { u8 id = iic_get_id(iic); return soft_iic_cfg[id].sda; } static inline u32 iic_get_delay(soft_iic_dev iic) { u8 id = iic_get_id(iic); return soft_iic_cfg[id].delay; } static inline u32 iic_get_io_pu(soft_iic_dev iic) { u8 id = iic_get_id(iic); return soft_iic_cfg[id].io_pu; } //------------------------------------------------------- int soft_iic_init(soft_iic_dev iic) { u32 scl, sda; scl = iic_get_scl(iic);//PA07引脚 sda = iic_get_sda(iic);//PA08引脚 if (iic_get_io_pu(iic)) { IIC_SCL_SET_PU(scl, 1);//打开上拉电阻 IIC_SDA_SET_PU(sda, 1); } else { IIC_SCL_SET_PU(scl, 0);//打开上拉电阻 IIC_SDA_SET_PU(sda, 0); } gpio_set_hd(scl, 0); //1:增强输出;0:不增强输出 gpio_set_hd0(scl, 1);//1:增强输出;0:不增强输出 gpio_set_hd(sda, 0); gpio_set_hd0(sda, 1); IIC_SDA_H(sda); IIC_SCL_H(scl); IIC_SCL_SET_PD(scl, 0); IIC_SCL_SET_DIE(scl, 1); IIC_SDA_SET_PD(sda, 0); IIC_SDA_SET_DIE(sda, 1); return 0; } void soft_iic_uninit(soft_iic_dev iic) { u32 scl, sda; scl = iic_get_scl(iic); sda = iic_get_sda(iic); IIC_SCL_DIR(scl, 1); IIC_SCL_SET_PU(scl, 0); IIC_SCL_SET_PD(scl, 0); IIC_SCL_SET_DIE(scl, 0); gpio_set_hd(scl, 0); gpio_set_hd0(scl, 0); IIC_SDA_DIR(sda, 1); IIC_SDA_SET_PU(sda, 0); IIC_SDA_SET_PD(sda, 0); IIC_SDA_SET_DIE(sda, 0); gpio_set_hd(sda, 0); gpio_set_hd0(sda, 0); } void soft_iic_suspend(soft_iic_dev iic) { u32 scl, sda; scl = iic_get_scl(iic); sda = iic_get_sda(iic); IIC_SCL_SET_DIE(scl, 0); IIC_SDA_SET_DIE(sda, 0); } void soft_iic_resume(soft_iic_dev iic) { u32 scl, sda; scl = iic_get_scl(iic); sda = iic_get_sda(iic); IIC_SCL_SET_DIE(scl, 1); IIC_SDA_SET_DIE(sda, 1); } void soft_iic_start(soft_iic_dev iic) { u32 scl, sda, dly_t; scl = iic_get_scl(iic); sda = iic_get_sda(iic); dly_t = iic_get_delay(iic); IIC_SDA_H(sda); delay(dly_t); IIC_SCL_H(scl); delay(dly_t * 2); IIC_SDA_L(sda); delay(dly_t); IIC_SCL_L(scl); delay(dly_t); } void soft_iic_stop(soft_iic_dev iic) { u32 scl, sda, dly_t; scl = iic_get_scl(iic); sda = iic_get_sda(iic); dly_t = iic_get_delay(iic); IIC_SDA_L(sda); delay(dly_t); IIC_SCL_H(scl); delay(dly_t * 2); IIC_SDA_H(sda); delay(dly_t); } static u8 soft_iic_check_ack(soft_iic_dev iic) { u8 ack; u32 scl, sda, dly_t; scl = iic_get_scl(iic); sda = iic_get_sda(iic); dly_t = iic_get_delay(iic); IIC_SDA_DIR(sda, 1); IIC_SCL_L(scl); delay(dly_t); IIC_SCL_H(scl); delay(dly_t); if (IIC_SDA_READ(sda) == 0) { ack = 1; } else { ack = 0; } delay(dly_t); IIC_SCL_L(scl); delay(dly_t); IIC_SDA_DIR(sda, 0); IIC_SDA_L(sda); return ack; } static void soft_iic_rx_ack(soft_iic_dev iic) { u32 scl, sda, dly_t; scl = iic_get_scl(iic); sda = iic_get_sda(iic); dly_t = iic_get_delay(iic); IIC_SDA_L(sda); delay(dly_t); IIC_SCL_H(scl); delay(dly_t * 2); IIC_SCL_L(scl); delay(dly_t); } static void soft_iic_rx_nack(soft_iic_dev iic) { u32 scl, sda, dly_t; scl = iic_get_scl(iic); sda = iic_get_sda(iic); dly_t = iic_get_delay(iic); IIC_SDA_H(sda); delay(dly_t); IIC_SCL_H(scl); delay(dly_t * 2); IIC_SCL_L(scl); delay(dly_t); } u8 soft_iic_tx_byte(soft_iic_dev iic, u8 byte) { u8 i, ret; u32 scl, sda, dly_t; scl = iic_get_scl(iic); sda = iic_get_sda(iic); dly_t = iic_get_delay(iic); IIC_SCL_L(scl); for (i = 0; i < 8; i++) { //MSB FIRST if ((byte << i) & 0x80) { IIC_SDA_H(sda); } else { IIC_SDA_L(sda); } delay(dly_t); IIC_SCL_H(scl); delay(dly_t * 2); IIC_SCL_L(scl); delay(dly_t); } return soft_iic_check_ack(iic); } u8 soft_iic_rx_byte(soft_iic_dev iic, u8 ack) { u8 byte = 0, i; u32 scl, sda, dly_t; scl = iic_get_scl(iic); sda = iic_get_sda(iic); dly_t = iic_get_delay(iic); IIC_SDA_DIR(sda, 1); for (i = 0; i < 8; i++) { delay(dly_t); IIC_SCL_H(scl); delay(dly_t); byte = byte << 1; if (IIC_SDA_READ(sda)) { byte |= 1; } delay(dly_t); IIC_SCL_L(scl); delay(dly_t); } IIC_SDA_DIR(sda, 0); if (ack) { soft_iic_rx_ack(iic); } else { soft_iic_rx_nack(iic); } return byte; } int soft_iic_read_buf(soft_iic_dev iic, void *buf, int len) { int i = 0; if (!buf || !len) { return -1; } for (i = 0; i < len - 1; i++) { ((u8 *)buf)[i] = soft_iic_rx_byte(iic, 1); } ((u8 *)buf)[len - 1] = soft_iic_rx_byte(iic, 0); return len; } int soft_iic_write_buf(soft_iic_dev iic, const void *buf, int len) { int i; u8 ack; if (!buf || !len) { return -1; } for (i = 0; i < len; i++) { ack = soft_iic_tx_byte(iic, ((u8 *)buf)[i]); if (ack == 0) { break; } } return i; } 根据ac6321a4提供的软件iic代码进行分析,如何才能使ac6321a4芯片获取sc7a20h加速度传感器的数据
最新发布
07-24
#include "MPU6050_I2C.h" /* 函数功能:MPU6050引脚初始化 函数参数:void 函数返回值:void 备注:PB10->SDA,PB11->SCL,开漏输出 */ void MPU6050_IIC_IO_Init(void) { My_GPIO_Init(MPU6050_IIC_GPIO,MPU6050_IIC_SCL_Pin|MPU6050_IIC_SDA_Pin,GPIO_KL_OUT,GPIO_P_NO,GPIO_50MHz); MPU6050_IIC_SCL = 1; MPU6050_IIC_SDA = 1; } //SDA的输出,开漏输出 void MPU6050_IIC_SDA_IO_OUT(void) { My_GPIO_Init(MPU6050_IIC_GPIO,MPU6050_IIC_SDA_Pin,GPIO_KL_OUT,GPIO_P_NO,GPIO_50MHz); } //SDA输入,上拉输入 void MPU6050_IIC_SDA_IO_IN(void) { My_GPIO_Init(MPU6050_IIC_GPIO,MPU6050_IIC_SDA_Pin,GPIO_FK_IN,GPIO_P_UP,GPIO_50MHz); } //IIC起始信号 void MPU6050_IIC_Start(void) { MPU6050_IIC_SDA_IO_OUT(); MPU6050_IIC_SCL = 1; MPU6050_IIC_SDA = 1; MPU6050_IIC_delay_4us(); MPU6050_IIC_SDA = 0; MPU6050_IIC_delay_4us(); MPU6050_IIC_SCL = 0; } //IIC停止信号 void MPU6050_IIC_Stop(void) { MPU6050_IIC_SDA_IO_OUT(); MPU6050_IIC_SCL = 0; MPU6050_IIC_SDA = 0; MPU6050_IIC_delay_4us(); MPU6050_IIC_SCL = 1; MPU6050_IIC_delay_4us(); MPU6050_IIC_SDA = 1; MPU6050_IIC_delay_4us(); } /* 函数功能:主机等待从机应答信号 函数参数:void 函数返回值:u8 备注:1,无效应答;0,有效应答 */ u8 MPU6050_IIC_Read_Ack(void) { u8 ucErrTime = 0; MPU6050_IIC_SDA_IO_IN(); //SDA输入 MPU6050_IIC_SDA = 1; MPU6050_IIC_delay_4us(); MPU6050_IIC_SCL = 1; //保证从机应答信号传输 MPU6050_IIC_delay_4us(); while(MPU6050_IIC_SDA_IN) //等待有效应答 { ucErrTime++; if(ucErrTime > 250) { MPU6050_IIC_Stop(); return 1; //无效应答 } } MPU6050_IIC_SCL = 0; //保证数据的准备 return 0; //有效应答 } /* 函数功能:主机发送应答信号 函数参数:u8 ack 函数返回值:void 备注:1,无效应答;0,有效应答 */ void MPU6050_IIC_Send_Ack(u8 ack) { MPU6050_IIC_SDA_IO_OUT(); MPU6050_IIC_SCL = 1; }
07-19
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

heda3

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值