#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; // 返回读取到的字节 }