123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- #include "IICs.h"
- #define IIC_SCL_OUT_1(port, pin) (port->BSRR = (uint32_t)pin) // 置1
- #define IIC_SCL_OUT_0(port, pin) (port->BRR = (uint32_t)pin)
- #define IIC_SDA_OUT_1(port, pin) (port->BSRR = (uint32_t)pin) // 置1
- #define IIC_SDA_OUT_0(port, pin) (port->BRR = (uint32_t)pin)
- #define IIC_SDA_IN(port, pin) ((port->IDR & pin) != 0)
- struct IIC_CONFIG {
- uint32_t IIC_SDA_CLK;
- GPIO_TypeDef* IIC_SDA_PORT;
- uint16_t IIC_SDA_PIN;
- uint32_t IIC_SCL_CLK;
- GPIO_TypeDef* IIC_SCL_PORT;
- uint16_t IIC_SCL_PIN;
- } iic_config[] = {
- {RCC_APB2Periph_GPIOB, GPIOB, GPIO_Pin_0, RCC_APB2Periph_GPIOB, GPIOB, GPIO_Pin_1},
- {RCC_APB2Periph_GPIOA, GPIOA, GPIO_Pin_6, RCC_APB2Periph_GPIOA, GPIOA, GPIO_Pin_7}
- };
- /**
- * @brief IIC延时
- * @param None
- * @retval None
- */
- static void IIC_Delay(uint8_t iicNo)
- {
- static uint16_t delayTime[] = {400, 400};
- uint16_t i;
- /*
- 下面的时间是通过逻辑分析仪测试得到的。
- 工作条件:CPU主频72MHz ,MDK编译环境,1级优化
-
- 循环次数为10时,SCL频率 = 205KHz
- 循环次数为7时,SCL频率 = 347KHz, SCL高电平时间1.5us,SCL低电平时间2.87us
- 循环次数为5时,SCL频率 = 421KHz, SCL高电平时间1.25us,SCL低电平时间2.375us
- */
- for (i = 0; i < delayTime[iicNo]; i++);
- }
- /**
- * @brief SDA输出方向配置
- * @param None
- * @retval None
- */
- void Set_IIC_SDA_OUT(uint8_t iicNo)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- RCC_APB2PeriphClockCmd(iic_config[iicNo].IIC_SDA_CLK, ENABLE);
- GPIO_InitStructure.GPIO_Pin=iic_config[iicNo].IIC_SDA_PIN;
- GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD;
- GPIO_Init(iic_config[iicNo].IIC_SDA_PORT,&GPIO_InitStructure);
- }
- /**
- * @brief SDA输入方向配置
- * @param None
- * @retval None
- */
- void Set_IIC_SDA_IN(uint8_t iicNo)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- RCC_APB2PeriphClockCmd(iic_config[iicNo].IIC_SDA_CLK, ENABLE);
- GPIO_InitStructure.GPIO_Pin=iic_config[iicNo].IIC_SDA_PIN;
- GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
- GPIO_Init(iic_config[iicNo].IIC_SDA_PORT,&GPIO_InitStructure);
- }
- /**
- * @brief 模拟IIC初始化
- * @param None
- * @retval None
- */
- void IIC_init(uint8_t iicNo)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- RCC_APB2PeriphClockCmd(iic_config[iicNo].IIC_SDA_CLK | iic_config[iicNo].IIC_SCL_CLK, ENABLE);
- GPIO_InitStructure.GPIO_Pin = iic_config[iicNo].IIC_SDA_PIN;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(iic_config[iicNo].IIC_SDA_PORT, &GPIO_InitStructure);
- GPIO_InitStructure.GPIO_Pin = iic_config[iicNo].IIC_SCL_PIN;
- GPIO_Init(iic_config[iicNo].IIC_SCL_PORT, &GPIO_InitStructure);
- IIC_stop(iicNo);
- }
- /**
- * @brief 模拟IIC起始信号
- * @param None
- * @retval None
- */
- void IIC_start(uint8_t iicNo)
- {
- Set_IIC_SDA_OUT(iicNo);
- IIC_SCL_OUT_1(iic_config[iicNo].IIC_SCL_PORT, iic_config[iicNo].IIC_SCL_PIN);
- IIC_SDA_OUT_1(iic_config[iicNo].IIC_SDA_PORT, iic_config[iicNo].IIC_SDA_PIN);
- IIC_Delay(iicNo);
- IIC_SDA_OUT_0(iic_config[iicNo].IIC_SDA_PORT, iic_config[iicNo].IIC_SDA_PIN);
- IIC_Delay(iicNo);
- IIC_SCL_OUT_0(iic_config[iicNo].IIC_SCL_PORT, iic_config[iicNo].IIC_SCL_PIN);
- IIC_Delay(iicNo);
- }
- /**
- * @brief 模拟IIC停止信号
- * @param None
- * @retval None
- */
- void IIC_stop(uint8_t iicNo)
- {
- Set_IIC_SDA_OUT(iicNo);
- IIC_SCL_OUT_1(iic_config[iicNo].IIC_SCL_PORT, iic_config[iicNo].IIC_SCL_PIN);
- IIC_SDA_OUT_0(iic_config[iicNo].IIC_SDA_PORT, iic_config[iicNo].IIC_SDA_PIN);
- IIC_Delay(iicNo);
- IIC_SDA_OUT_1(iic_config[iicNo].IIC_SDA_PORT, iic_config[iicNo].IIC_SDA_PIN);
- }
- /**
- * @brief 模拟IIC主机应答
- * @param None
- * @retval None
- */
- void IIC_ack(uint8_t iicNo)
- {
- Set_IIC_SDA_OUT(iicNo);
- IIC_SDA_OUT_0(iic_config[iicNo].IIC_SDA_PORT, iic_config[iicNo].IIC_SDA_PIN);
- IIC_Delay(iicNo);
- IIC_SCL_OUT_1(iic_config[iicNo].IIC_SCL_PORT, iic_config[iicNo].IIC_SCL_PIN);
- IIC_Delay(iicNo);
- IIC_SCL_OUT_0(iic_config[iicNo].IIC_SCL_PORT, iic_config[iicNo].IIC_SCL_PIN);
- IIC_Delay(iicNo);
- IIC_SDA_OUT_1(iic_config[iicNo].IIC_SDA_PORT, iic_config[iicNo].IIC_SDA_PIN);
- }
- /**
- * @brief 模拟IIC主机不应答
- * @param None
- * @retval None
- */
- void IIC_noack(uint8_t iicNo)
- {
- Set_IIC_SDA_OUT(iicNo);
- IIC_SDA_OUT_1(iic_config[iicNo].IIC_SDA_PORT, iic_config[iicNo].IIC_SDA_PIN);
- IIC_Delay(iicNo);
- IIC_SCL_OUT_1(iic_config[iicNo].IIC_SCL_PORT, iic_config[iicNo].IIC_SCL_PIN);
- IIC_Delay(iicNo);
- IIC_SCL_OUT_0(iic_config[iicNo].IIC_SCL_PORT, iic_config[iicNo].IIC_SCL_PIN);
- IIC_Delay(iicNo);
- }
- /**
- * @brief 模拟IIC等待从机应答
- * @param None
- * @retval 1: 接收应答失败 0: 接收应答成功
- */
- uint8_t IIC_wait_ack(uint8_t iicNo)
- {
- uint8_t rec = 0;
- Set_IIC_SDA_OUT(iicNo);
- IIC_SDA_OUT_1(iic_config[iicNo].IIC_SDA_PORT, iic_config[iicNo].IIC_SDA_PIN);
- IIC_Delay(iicNo);
- Set_IIC_SDA_IN(iicNo);
- IIC_SCL_OUT_1(iic_config[iicNo].IIC_SCL_PORT, iic_config[iicNo].IIC_SCL_PIN);
- IIC_Delay(iicNo);
- rec = IIC_SDA_IN(iic_config[iicNo].IIC_SDA_PORT, iic_config[iicNo].IIC_SDA_PIN);
- IIC_SCL_OUT_0(iic_config[iicNo].IIC_SCL_PORT, iic_config[iicNo].IIC_SCL_PIN);
- IIC_Delay(iicNo);
-
- return rec;
- }
- /**
- * @brief 模拟IIC发送一个字节
- * @param None
- * @retval None
- */
- void IIC_send_byte(uint8_t iicNo, uint8_t txd)
- {
- uint8_t i=0;
- Set_IIC_SDA_OUT(iicNo);
- for(i=0;i<8;i++)
- {
- if(txd&0x80) IIC_SDA_OUT_1(iic_config[iicNo].IIC_SDA_PORT, iic_config[iicNo].IIC_SDA_PIN);
- else IIC_SDA_OUT_0(iic_config[iicNo].IIC_SDA_PORT, iic_config[iicNo].IIC_SDA_PIN);
- IIC_Delay(iicNo);
- IIC_SCL_OUT_1(iic_config[iicNo].IIC_SCL_PORT, iic_config[iicNo].IIC_SCL_PIN);
- IIC_Delay(iicNo); // 发送数据
- IIC_SCL_OUT_0(iic_config[iicNo].IIC_SCL_PORT, iic_config[iicNo].IIC_SCL_PIN);
- if(i == 7) IIC_SDA_OUT_1(iic_config[iicNo].IIC_SDA_PORT, iic_config[iicNo].IIC_SDA_PIN); // 最后一位数据发送完要释放SDA总线
- txd <<= 1;
- IIC_Delay(iicNo);
- }
- }
- /**
- * @brief 模拟IIC读取一个字节
- * @param ack: 0,读完不产生应答 1,读完产生应答
- * @retval 返回读取到的字节
- */
- uint8_t IIC_read_byte(uint8_t iicNo, uint8_t ack)
- {
- uint8_t i,receive=0;
- Set_IIC_SDA_IN(iicNo);
- for(i=0;i<8;i++)
- {
- receive <<= 1;
- IIC_SCL_OUT_1(iic_config[iicNo].IIC_SCL_PORT, iic_config[iicNo].IIC_SCL_PIN);
- IIC_Delay(iicNo);
- if(IIC_SDA_IN(iic_config[iicNo].IIC_SDA_PORT, iic_config[iicNo].IIC_SDA_PIN)) receive++; // 连续读取八位
- IIC_SCL_OUT_0(iic_config[iicNo].IIC_SCL_PORT, iic_config[iicNo].IIC_SCL_PIN);
- IIC_Delay(iicNo);
- }
- if(!ack) IIC_noack(iicNo);
- else IIC_ack(iicNo);
- return receive; // 返回读取到的字节
- }
|