0
点赞
收藏
分享

微信扫一扫

STM32 I2C源码

乌龙茶3297 2022-04-14 阅读 99
stm32c语言

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;
}

举报

相关推荐

0 条评论