I2C通讯协议和原理这里不说,网上一大堆,自己查。直接上源码,一直用着的,没有任何问题,里面的函数都是我自己常用的一些,如果有其他需要,可以根据这些代码仿照写就行。
定义IIC结构体:
typedef struct
{
GPIO_TypeDef *SCL_GPIO;
uint16_t SCL_GPIO_PIN;
GPIO_TypeDef *SDA_GPIO;
uint16_t SDA_GPIO_PIN;
}typedef_I2C;
主文件代码:
#include "i2c.h"
#include "delay.h"
//设置I2C引脚
void I2C_setpin(typedef_I2C *i2c,GPIO_TypeDef *gpio_sck,uint16_t pin_sck,GPIO_TypeDef *gpio_sda,uint16_t pin_sda)
{
i2c->SCL_GPIO=gpio_sck;
i2c->SDA_GPIO=gpio_sda;
i2c->SCL_GPIO_PIN=pin_sck;
i2c->SDA_GPIO_PIN=pin_sda;
}
//设置SDA引脚为输入
void IIC_SDA_IN(typedef_I2C *iic)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = iic->SDA_GPIO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(iic->SDA_GPIO, &GPIO_InitStruct);
}
//设置SDA引脚为输出
void IIC_SDA_OUT(typedef_I2C *iic)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = iic->SDA_GPIO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(iic->SDA_GPIO, &GPIO_InitStruct);
}
void IIC_set_clk1(typedef_I2C *iic)
{
HAL_GPIO_WritePin(iic->SCL_GPIO, iic->SCL_GPIO_PIN, GPIO_PIN_SET);
}
void IIC_set_clk0(typedef_I2C *iic)
{
HAL_GPIO_WritePin(iic->SCL_GPIO, iic->SCL_GPIO_PIN, GPIO_PIN_RESET);
}
void IIC_set_sda1(typedef_I2C *iic)
{
HAL_GPIO_WritePin(iic->SDA_GPIO, iic->SDA_GPIO_PIN, GPIO_PIN_SET);
}
void IIC_set_sda0(typedef_I2C *iic)
{
HAL_GPIO_WritePin(iic->SDA_GPIO, iic->SDA_GPIO_PIN, GPIO_PIN_RESET);
}
uint16_t IIC_get_sda(typedef_I2C *iic)
{
return HAL_GPIO_ReadPin(iic->SDA_GPIO,iic->SDA_GPIO_PIN)==GPIO_PIN_SET;
}
//开始标志
void IIC_start(typedef_I2C *iic)
{
IIC_SDA_OUT(iic);
IIC_set_sda1(iic);
IIC_set_clk1(iic);
delay_us(1);
IIC_set_sda0(iic); //Start
delay_us(1);
IIC_set_clk0(iic);
delay_us(1);
}
//结束标志
void IIC_stop(typedef_I2C *iic)
{
IIC_SDA_OUT(iic);
IIC_set_clk0(iic);
delay_us(1); //Stop
IIC_set_sda0(iic);
delay_us(1); //Stop
IIC_set_clk1(iic);
delay_us(1);
IIC_set_sda1(iic);
delay_us(1);
}
//等待从机应答
uint8_t IIC_wait_ack(typedef_I2C *iic)
{
uint16_t errtime=0;
IIC_SDA_IN(iic);
IIC_set_sda1(iic);
delay_us(1);
IIC_set_clk1(iic);
delay_us(1);
while(IIC_get_sda(iic))
{
errtime++;
if(errtime>500)
{
IIC_stop(iic);
return 1;
}
}
IIC_set_clk0(iic);
return 0;
}
//对从机进行应答
void IIC_ack(typedef_I2C *iic)
{
IIC_set_clk0(iic);
delay_us(1);
IIC_SDA_OUT(iic);
IIC_set_sda0(iic);
delay_us(1);
IIC_set_clk1(iic);
delay_us(1);
IIC_set_clk0(iic);
delay_us(1);
}
void IIC_noack(typedef_I2C *iic)
{
IIC_set_clk0(iic);
delay_us(1);
IIC_SDA_OUT(iic);
IIC_set_sda1(iic);
delay_us(1);
IIC_set_clk1(iic);
delay_us(1);
IIC_set_clk0(iic);
delay_us(1);
}
//写单字节
void IIC_writebyte(typedef_I2C *iic,uint8_t datas)
{
uint8_t i;
IIC_SDA_OUT(iic);
IIC_set_clk0(iic);
for(i=0;i<8;i++)
{
delay_us(1);
if(datas&0x80)
IIC_set_sda1(iic);
else
IIC_set_sda0(iic);
datas=datas<<1;
// delay(2);
delay_us(1);
IIC_set_clk1(iic);
delay_us(1);
IIC_set_clk0(iic);
delay_us(1);
}
}
//读单字节
uint8_t IIC_readbyte(typedef_I2C *iic,uint8_t ack)
{
uint8_t i,datas;
IIC_set_sda1(iic);
IIC_SDA_IN(iic);
for(i=0;i<8;i++)
{
datas=datas<<1;
IIC_set_clk0(iic);
delay_us(1);
IIC_set_clk1(iic);
delay_us(1);
if(IIC_get_sda(iic))
datas|=0x01;
delay_us(1);
}
IIC_set_clk0(iic);
if(!ack)
IIC_noack(iic);
else
IIC_ack(iic);
return datas;
}
//写3个字节(24bit)的整形数
void IIC_write_reg32(typedef_I2C *iic,uint8_t s_addr,uint8_t r_addr,uint32_t val)
{
IIC_start(iic);
IIC_writebyte(iic,s_addr);
IIC_wait_ack(iic);
IIC_writebyte(iic,r_addr);
IIC_wait_ack(iic);
IIC_writebyte(iic,(val>>16)&0xff);
IIC_wait_ack(iic);
IIC_writebyte(iic,(val>>8)&0xff);
IIC_wait_ack(iic);
IIC_writebyte(iic,val&0xff);
IIC_wait_ack(iic);
IIC_stop(iic);
delay_ms(1);
}
//向指定16位地址的单个字节写数
void IIC_write_sram16_8(typedef_I2C *iic,uint8_t s_addr,uint16_t r_addr,uint8_t val)
{
IIC_start(iic);
IIC_writebyte(iic,s_addr);
IIC_wait_ack(iic);
IIC_writebyte(iic,r_addr>>8);
IIC_wait_ack(iic);
IIC_writebyte(iic,r_addr&0x00ff);
IIC_wait_ack(iic);
IIC_writebyte(iic,val);
IIC_wait_ack(iic);
IIC_stop(iic);
delay_ms(1);
}
//向指定开始地址(16位)的连续N个地址写数
void IIC_write_sram16_n(typedef_I2C *iic,uint8_t s_addr,uint8_t *source,uint16_t r_addr,uint8_t nums)
{
IIC_start(iic);
IIC_writebyte(iic,s_addr);
IIC_wait_ack(iic);
IIC_writebyte(iic,r_addr>>8);
IIC_wait_ack(iic);
IIC_writebyte(iic,r_addr&0x00ff);
IIC_wait_ack(iic);
for(;nums>0;nums--)
{
IIC_writebyte(iic,*source);
source++;
IIC_wait_ack(iic);
}
IIC_stop(iic);
delay_ms(1);
}
//向指定开始地址(8位)的连续N个地址写数
void IIC_write_sram8_n(typedef_I2C *iic,uint8_t s_addr,uint8_t *source,uint8_t r_addr,uint8_t nums)
{
IIC_start(iic);
IIC_writebyte(iic,s_addr);
IIC_wait_ack(iic);
IIC_writebyte(iic,r_addr);
IIC_wait_ack(iic);
for(;nums>0;nums--)
{
IIC_writebyte(iic,*source);
source++;
IIC_wait_ack(iic);
}
IIC_stop(iic);
delay_ms(1);
}
//向指定8位地址的单个字节写入24位(3字节)数
void IIC_write_sram8_24(typedef_I2C *iic,uint8_t s_addr,uint8_t r_addr,uint32_t val)
{
IIC_start(iic);
IIC_writebyte(iic,s_addr);
IIC_wait_ack(iic);
IIC_writebyte(iic,r_addr);
IIC_wait_ack(iic);
IIC_writebyte(iic,(val>>16)&0xff);
IIC_wait_ack(iic);
IIC_writebyte(iic,(val>>8)&0xff);
IIC_wait_ack(iic);
IIC_writebyte(iic,(val)&0xff);
IIC_wait_ack(iic);
IIC_stop(iic);
delay_ms(1);
}
//向指定8位地址的单个字节写入8位(单字节)数
void IIC_write_sram8_8(typedef_I2C *iic,uint8_t s_addr,uint8_t r_addr,uint8_t val)
{
IIC_start(iic);
IIC_writebyte(iic,s_addr);
IIC_wait_ack(iic);
IIC_writebyte(iic,r_addr);
IIC_wait_ack(iic);
IIC_writebyte(iic,val);
IIC_wait_ack(iic);
IIC_stop(iic);
delay_ms(1);
}
//写入单字节指令
void IIC_write_op(typedef_I2C *iic,uint8_t s_addr,uint8_t opcode)
{
IIC_start(iic);
IIC_writebyte(iic,s_addr);
IIC_wait_ack(iic);
IIC_writebyte(iic,opcode);
IIC_wait_ack(iic);
IIC_stop(iic);
delay_ms(1);
}
//读取指定地址(8位)的数值(24位)
uint32_t IIC_read_reg32(typedef_I2C *iic,uint8_t s_addr,uint8_t s_addr_read,uint8_t r_addr)
{
uint32_t temp=0;
IIC_start(iic);
IIC_writebyte(iic,s_addr);
IIC_wait_ack(iic);
IIC_writebyte(iic,r_addr);
IIC_wait_ack(iic);
IIC_start(iic);
IIC_writebyte(iic,s_addr_read);
IIC_wait_ack(iic);
temp=(IIC_readbyte(iic,1)<<16);
temp|=(IIC_readbyte(iic,1)<<8);
temp|=IIC_readbyte(iic,0);
IIC_stop(iic);
return temp;
}
uint8_t IIC_read_sram8_8(typedef_I2C *iic,uint8_t s_addr,uint8_t s_addr_read,uint8_t r_addr)
{
uint8_t temp=0;
IIC_start(iic);
IIC_writebyte(iic,s_addr);
IIC_wait_ack(iic);
IIC_writebyte(iic,r_addr);
IIC_wait_ack(iic);
IIC_start(iic);
IIC_writebyte(iic,s_addr_read);
IIC_wait_ack(iic);
temp= IIC_readbyte(iic,0);
IIC_stop(iic);
return temp;
}
uint8_t IIC_read_sram16_8(typedef_I2C *iic,uint8_t s_addr,uint8_t s_addr_read,uint16_t r_addr)
{
uint8_t temp=0;
IIC_start(iic);
IIC_writebyte(iic,s_addr);
IIC_wait_ack(iic);
IIC_writebyte(iic,r_addr>>8);
IIC_wait_ack(iic);
IIC_writebyte(iic,r_addr&0xff);
IIC_wait_ack(iic);
IIC_start(iic);
IIC_writebyte(iic,s_addr_read);
IIC_wait_ack(iic);
temp= IIC_readbyte(iic,0);
IIC_stop(iic);
return temp;
}
//连续读取N个数值
uint8_t IIC_read_sram16_n(typedef_I2C *iic,uint8_t s_addr,uint8_t s_addr_read,uint8_t *source,uint16_t r_addr,uint8_t nums)
{
uint8_t temp=0;
IIC_start(iic);
IIC_writebyte(iic,s_addr);
IIC_wait_ack(iic);
IIC_writebyte(iic,r_addr>>8);
IIC_wait_ack(iic);
IIC_writebyte(iic,r_addr&0xff);
IIC_wait_ack(iic);
IIC_start(iic);
IIC_writebyte(iic,s_addr_read);
IIC_wait_ack(iic);
for(;nums>1;nums--)
{
*source=IIC_readbyte(iic,1);
source++;
}
*source=IIC_readbyte(iic,0);
IIC_stop(iic);
return temp;
}
uint8_t IIC_read_sram8_n(typedef_I2C *iic,uint8_t s_addr,uint8_t s_addr_read,uint8_t *source,uint8_t r_addr,uint8_t nums)
{
uint8_t temp=0;
IIC_start(iic);
IIC_writebyte(iic,s_addr);
IIC_wait_ack(iic);
IIC_writebyte(iic,r_addr);
IIC_wait_ack(iic);
IIC_start(iic);
IIC_writebyte(iic,s_addr_read);
IIC_wait_ack(iic);
for(;nums>1;nums--)
{
*source=IIC_readbyte(iic,1);
source++;
}
*source=IIC_readbyte(iic,0);
IIC_stop(iic);
return temp;
}
//读取无需寄存器地址的数据
uint8_t IIC_read_noaddr_n(typedef_I2C *iic,uint8_t s_addr_read,uint8_t *source,uint8_t nums)
{
uint8_t temp=0;
IIC_start(iic);
IIC_writebyte(iic,s_addr_read);
IIC_wait_ack(iic);
for(;nums>1;nums--)
{
*source=IIC_readbyte(iic,1);
source++;
}
*source=IIC_readbyte(iic,0);
IIC_stop(iic);
return temp;
}