你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32 模拟IIC源代码 多个I2C减少冗余代码

[复制链接]
STMCU小助手 发布时间:2022-10-12 21:32
当设计中使用I2C的数量多于1个时,其底层I2C的代码逻辑都是一样的,只有IO口变了,为此还要复制粘贴、修改IO,不仅费时,而且还浪费片内资源,因此可以使用指针来重复执行IIC底层代码,实现一个代码,多个IO使用。
注意:使用什么IO口,一定要打开其IO时钟,同时配置为输出开漏模式!!!
使用例程在最下面

Stm32f30x_SMLT_I2C.h


  1. #ifndef __Stm32f30x_SMLT_I2C_H
  2. #define __Stm32f30x_SMLT_I2C_H

  3. //========================= Include ===============================================================

  4. #include "stm32f30x.h"

  5. //========================= Variable ==============================================================

  6. typedef struct
  7. {
  8.         GPIO_TypeDef* SDA_GPIO;        //SDA的GPIO组地址
  9.         GPIO_TypeDef* SCL_GPIO;        //SCL的GPIO组地址
  10.         uint32_t SDA_SBIT;                //SDA 在 BSRR寄存器 中的置位
  11.         uint32_t SDA_RBIT;                //SDA 在 BSRR寄存器 中的复位
  12.         uint32_t SCL_SBIT;                //SCL 在 BSRR寄存器 中的置位
  13.         uint32_t SCL_RBIT;                //SCL 在 BSRR寄存器 中的复位
  14.         uint32_t SDA_MODER;                //SDA 在 MODER寄存器 中的配置位
  15.         uint32_t SDA_MODER_0;        //SDA 在 MODER寄存器 中的配置位低位
  16.         uint32_t SDA_MODER_1;        //SDA 在 MODER寄存器 中的配置位高位
  17.         uint8_t SCL_Delay;                //SCL的延时参数 调整波特率 越大波特率越大
  18. }I2C_Struct;

  19. extern I2C_Struct S_I2C_IO[2];//------------------------------------- 修改处
  20. //(想要3个的话,数组添加,下面的define也要添加,初始化函数S_I2C_Init中也要添加)

  21. //========================= I2C1_Define ================================================================
  22. //--------------------------SDA-------------------------------------- 修改处
  23. #define S_I2C1_SDA_GPIO                GPIOE
  24. #define S_I2C1_SDA_BIT                0
  25. //--------------------------SCL-------------------------------------- 修改处
  26. #define S_I2C1_SCL_GPIO                GPIOE
  27. #define S_I2C1_SCL_BIT                1
  28. #define S_I2C1_SCL_DELAY        0x80
  29. //还需配置结构体初始化函数 S_I2C_Init 别忘了打开时钟及开漏配置

  30. //========================= I2C2_Define ================================================================
  31. //--------------------------SDA-------------------------------------- 修改处
  32. #define S_I2C2_SDA_GPIO                GPIOE
  33. #define S_I2C2_SDA_BIT                11
  34. //--------------------------SCL-------------------------------------- 修改处
  35. #define S_I2C2_SCL_GPIO                GPIOB
  36. #define S_I2C2_SCL_BIT                13
  37. #define S_I2C2_SCL_DELAY        0x10
  38. //还需配置结构体初始化函数 S_I2C_Init 别忘了打开时钟及开漏配置

  39. // //========================= I2Cx_Define ================================================================
  40. // //--------------------------SDA-------------------------------------- 修改处
  41. // #define S_I2Cx_SDA_GPIO                GPIOx
  42. // #define S_I2Cx_SDA_BIT                x
  43. // //--------------------------SCL-------------------------------------- 修改处
  44. // #define S_I2Cx_SCL_GPIO                GPIOx
  45. // #define S_I2Cx_SCL_BIT                x
  46. // #define S_I2Cx_SCL_DELAY                x
  47. // //添加在此添加


  48. //========================= Function ==============================================================

  49. void S_I2C_Init(void);//--------------------------------------------- 修改处

  50. void S_I2C_Start(I2C_Struct I2C_temp);
  51. void S_I2C_Stop(I2C_Struct I2C_temp);
  52. uint8_t S_I2C_SendByte(I2C_Struct I2C_temp, uint8_t byte);
  53. uint8_t S_I2C_ReceiveByte(I2C_Struct I2C_temp, uint8_t nack);
  54. uint8_t S_I2C_WriteRegister(I2C_Struct I2C_temp, uint8_t addr, uint8_t regAddr, uint8_t data);
  55. uint8_t S_I2C_ReadRegister(I2C_Struct I2C_temp, uint8_t addr, uint8_t regAddr, uint8_t amount, uint8_t* data, uint8_t typ);
  56. uint8_t S_I2C_PointerRead(I2C_Struct I2C_temp, uint8_t addr, uint8_t regAddr, uint8_t amount, uint8_t* data, uint8_t typ);

  57. //========================= Define ================================================================
  58. //通过宏定义将IO结构体直接放入基础函数中
  59. //-------------------------- I2C1 -----------------------------------
  60. #define S_I2C1_Start()                                                                                        S_I2C_Start(S_I2C_IO[0])
  61. #define S_I2C1_Stop()                                                                                        S_I2C_Stop(S_I2C_IO[0])
  62. #define S_I2C1_SendByte(byte)                                                                        S_I2C_SendByte(S_I2C_IO[0], byte)
  63. #define S_I2C1_ReceiveByte(nack)                                                                S_I2C_ReceiveByte(S_I2C_IO[0], nack)
  64. #define S_I2C1_WriteRegister(addr, regAddr, data)                                S_I2C_WriteRegister(S_I2C_IO[0], addr, regAddr, data)
  65. #define S_I2C1_ReadRegister(addr, regAddr, amount, data, typ)        S_I2C_ReadRegister(S_I2C_IO[0], addr, regAddr, amount, data, typ)
  66. #define S_I2C1_PointerRead(addr, regAddr, amount, data, typ)        S_I2C_PointerRead(S_I2C_IO[0], addr, regAddr, amount, data, typ)

  67. //-------------------------- I2C2 -----------------------------------
  68. #define S_I2C2_Start()                                                                                        S_I2C_Start(S_I2C_IO[1])
  69. #define S_I2C2_Stop()                                                                                        S_I2C_Stop(S_I2C_IO[1])
  70. #define S_I2C2_SendByte(byte)                                                                        S_I2C_SendByte(S_I2C_IO[1], byte)
  71. #define S_I2C2_ReceiveByte(nack)                                                                S_I2C_ReceiveByte(S_I2C_IO[1], nack)
  72. #define S_I2C2_WriteRegister(addr, regAddr, data)                                S_I2C_WriteRegister(S_I2C_IO[1], addr, regAddr, data)
  73. #define S_I2C2_ReadRegister(addr, regAddr, amount, data, typ)        S_I2C_ReadRegister(S_I2C_IO[1], addr, regAddr, amount, data, typ)
  74. #define S_I2C2_PointerRead(addr, regAddr, amount, data, typ)        S_I2C_PointerRead(S_I2C_IO[1], addr, regAddr, amount, data, typ)

  75. //-------------------------- Another --------------------------------
  76. #define ACK                0
  77. #define NACK        1

  78. #define FAILED        0
  79. #define SUCCEED        1

  80. #define ARRAY        0
  81. #define STRUCT        1
  82. //=================================================================================================

  83. #endif
复制代码

Stm32f30x_SMLT_I2C.c

  1. #include "Stm32f30x_SMLT_I2C.h"

  2. I2C_Struct S_I2C_IO[2];//IO口结构体,通过.h文件定义使用的引脚

  3. /**
  4. * @description: I2C结构体IO初始化
  5. * @param {I2C_Struct*} I2C_temp        I2C的IO结构体
  6. * @param {GPIO_TypeDef*}        SDA_GPIO                I2C SDA GPIO(GPIOA~GPIOx)
  7. * @param {uint8_t}                        SDA_BIT                        I2C SDA引脚号(1~16)
  8. * @param {GPIO_TypeDef*}        SCL_GPIO                I2C SCL GPIO(GPIOA~GPIOx)
  9. * @param {uint8_t}                        SCL_BIT                        I2C SCL引脚号(1~16)
  10. * @param {uint8_t}                        SCL_Delay                I2C SCL时钟延时(0x00~0xff)越大波特率越低
  11. * @return {*}
  12. */
  13. void S_I2C_Struct_Init(I2C_Struct* I2C_temp, GPIO_TypeDef* SDA_GPIO, uint8_t SDA_BIT, GPIO_TypeDef* SCL_GPIO, uint8_t SCL_BIT, uint8_t SCL_Delay)
  14. {
  15.         I2C_temp->SDA_GPIO = SDA_GPIO;
  16.         I2C_temp->SCL_GPIO = SCL_GPIO;
  17.         I2C_temp->SDA_SBIT = (0x00000001 << SDA_BIT);
  18.         I2C_temp->SDA_RBIT = (0x00010000 << SDA_BIT);
  19.         I2C_temp->SCL_SBIT = (0x00000001 << SCL_BIT);
  20.         I2C_temp->SCL_RBIT = (0x00010000 << SCL_BIT);
  21.         I2C_temp->SDA_MODER = 0x00000003 << (SDA_BIT << 1);
  22.         I2C_temp->SDA_MODER_0 = 0x00000001 << (SDA_BIT << 1);
  23.         I2C_temp->SDA_MODER_1 = 0x00000002 << (SDA_BIT << 1);
  24.         I2C_temp->SCL_Delay = SCL_Delay;
  25. }

  26. /**
  27. * @description: I2C结构体总初始化,将计算的各个变量存入结构体中
  28. * @param {*}
  29. * @return {*}
  30. */
  31. void S_I2C_Init(void)
  32. {
  33.         S_I2C_Struct_Init(&S_I2C_IO[0], S_I2C1_SDA_GPIO, S_I2C1_SDA_BIT, S_I2C1_SCL_GPIO, S_I2C1_SCL_BIT, S_I2C1_SCL_DELAY);
  34.         S_I2C_Struct_Init(&S_I2C_IO[1], S_I2C2_SDA_GPIO, S_I2C2_SDA_BIT, S_I2C2_SCL_GPIO, S_I2C2_SCL_BIT, S_I2C2_SCL_DELAY);
  35.         // S_I2C_Struct_Init(&S_I2C_IO[x], S_I2Cx_SDA_GPIO, S_I2Cx_SDA_BIT, S_I2Cx_SCL_GPIO, S_I2Cx_SCL_BIT, S_I2Cx_SCL_DELAY);//添加在此添加
  36. }

  37. /**
  38. * @description: I2C时钟延时,调整波特率
  39. * @param {*}
  40. * @return {*}
  41. */
  42. void S_I2C_Delay(uint8_t temp)
  43. {
  44.     for ( ; temp; temp--)
  45.         {
  46.                 /* code */
  47.         }
  48. }

  49. /**
  50. * @description: 产生起始信号
  51. * @param {I2C_Struct} I2C_temp I2C_IO结构体
  52. * @return {*}
  53. */
  54. void S_I2C_Start(I2C_Struct I2C_temp)
  55. {
  56.         I2C_temp.SDA_GPIO->MODER |= I2C_temp.SDA_MODER_0;
  57.         I2C_temp.SDA_GPIO->BSRR |= I2C_temp.SDA_SBIT;
  58.         I2C_temp.SCL_GPIO->BSRR |= I2C_temp.SCL_SBIT;
  59.     S_I2C_Delay(I2C_temp.SCL_Delay);
  60.         I2C_temp.SDA_GPIO->BSRR |= I2C_temp.SDA_RBIT;
  61.     S_I2C_Delay(I2C_temp.SCL_Delay);
  62.         I2C_temp.SCL_GPIO->BSRR |= I2C_temp.SCL_RBIT;
  63.     S_I2C_Delay(I2C_temp.SCL_Delay);
  64. }

  65. /**
  66. * @description: 产生停止信号
  67. * @param {I2C_Struct} I2C_temp
  68. * @return {*}
  69. */
  70. void S_I2C_Stop(I2C_Struct I2C_temp)
  71. {
  72.         I2C_temp.SDA_GPIO->MODER |= I2C_temp.SDA_MODER_0;
  73.         I2C_temp.SCL_GPIO->BSRR |= I2C_temp.SCL_RBIT;
  74.         I2C_temp.SDA_GPIO->BSRR |= I2C_temp.SDA_RBIT;
  75.     S_I2C_Delay(I2C_temp.SCL_Delay);
  76.         I2C_temp.SCL_GPIO->BSRR |= I2C_temp.SCL_SBIT;
  77.     S_I2C_Delay(I2C_temp.SCL_Delay);
  78.         I2C_temp.SDA_GPIO->BSRR |= I2C_temp.SDA_SBIT;
  79.     S_I2C_Delay(I2C_temp.SCL_Delay);
  80. }

  81. /**
  82. * @description: 发送一个字节数据
  83. * @param {I2C_Struct} I2C_temp        I2C_IO结构体
  84. * @param {uint8_t} byte        数据
  85. * @return {uint8_t}                NACK
  86. *                                                         ACK
  87. */
  88. uint8_t S_I2C_SendByte(I2C_Struct I2C_temp, uint8_t byte)
  89. {
  90.         uint8_t temp = 0x00;
  91.         for(uint8_t i = 0x80; i; i >>= 1)
  92.         {
  93.                 I2C_temp.SCL_GPIO->BSRR |= I2C_temp.SCL_RBIT;
  94.                 if(byte & i)
  95.                 {
  96.                         I2C_temp.SDA_GPIO->BSRR |= I2C_temp.SDA_SBIT;
  97.                 }
  98.                 else
  99.                 {
  100.                         I2C_temp.SDA_GPIO->BSRR |= I2C_temp.SDA_RBIT;
  101.                 }
  102.         S_I2C_Delay(I2C_temp.SCL_Delay);
  103.                 I2C_temp.SCL_GPIO->BSRR |= I2C_temp.SCL_SBIT;
  104.         S_I2C_Delay(I2C_temp.SCL_Delay);
  105.         }
  106.         I2C_temp.SCL_GPIO->BSRR |= I2C_temp.SCL_RBIT;
  107.         I2C_temp.SDA_GPIO->MODER &= ~I2C_temp.SDA_MODER;
  108.         S_I2C_Delay(I2C_temp.SCL_Delay);
  109.         I2C_temp.SCL_GPIO->BSRR |= I2C_temp.SCL_SBIT;
  110.         if(I2C_temp.SDA_GPIO -> IDR & I2C_temp.SDA_SBIT)
  111.         {
  112.                 temp = NACK;
  113.         }
  114.         else
  115.         {
  116.                 temp = ACK;
  117.         }
  118.     S_I2C_Delay(I2C_temp.SCL_Delay);
  119.         I2C_temp.SDA_GPIO->BSRR |= I2C_temp.SDA_RBIT;
  120.         I2C_temp.SDA_GPIO->MODER |= I2C_temp.SDA_MODER_0;
  121.         I2C_temp.SCL_GPIO->BSRR |= I2C_temp.SCL_RBIT;
  122.     S_I2C_Delay(I2C_temp.SCL_Delay);
  123.         return temp;
  124. }

  125. /**
  126. * @description: 接收一个字节数据
  127. * @param {I2C_Struct} I2C_temp        I2C_IO结构体
  128. * @param {uint8_t} nack        接收后结束要发送的应答信号
  129. *                                                         NACK
  130. *                                                         ACK
  131. * @return {uint8_t}        接收到的字节
  132. */
  133. uint8_t S_I2C_ReceiveByte(I2C_Struct I2C_temp, uint8_t nack)
  134. {
  135.         uint8_t byte = 0x00;
  136.         I2C_temp.SDA_GPIO->MODER &= ~I2C_temp.SDA_MODER;
  137.         for (uint8_t i = 8; i; i--)
  138.         {
  139.                 I2C_temp.SCL_GPIO->BSRR |= I2C_temp.SCL_RBIT;
  140.         S_I2C_Delay(I2C_temp.SCL_Delay);
  141.                 byte <<= 1;
  142.                 I2C_temp.SCL_GPIO->BSRR |= I2C_temp.SCL_SBIT;
  143.                 if(I2C_temp.SDA_GPIO -> IDR & I2C_temp.SDA_SBIT)
  144.                 {
  145.                         byte |= 0x01;
  146.                 }
  147.         S_I2C_Delay(I2C_temp.SCL_Delay);
  148.         }
  149.         I2C_temp.SCL_GPIO->BSRR |= I2C_temp.SCL_RBIT;
  150.         I2C_temp.SDA_GPIO->BSRR |= I2C_temp.SDA_RBIT;
  151.         I2C_temp.SDA_GPIO->MODER |= I2C_temp.SDA_MODER_0;
  152.         if(nack)
  153.                 I2C_temp.SDA_GPIO->BSRR |= I2C_temp.SDA_SBIT;
  154.         else
  155.                 I2C_temp.SDA_GPIO->BSRR |= I2C_temp.SDA_RBIT;
  156.         I2C_temp.SCL_GPIO->BSRR |= I2C_temp.SCL_RBIT;
  157.     S_I2C_Delay(I2C_temp.SCL_Delay);
  158.         I2C_temp.SCL_GPIO->BSRR |= I2C_temp.SCL_SBIT;
  159.     S_I2C_Delay(I2C_temp.SCL_Delay);
  160.         return byte;
  161. }


  162. /**
  163. * @description: 写一个字节的寄存器
  164. * @param {I2C_Struct} I2C_temp        I2C_IO结构体
  165. * @param {uint8_t} addr        器件地址(0x00~0x7f)
  166. * @param {uint8_t} regAddr        寄存器地址(0x00~0xff)
  167. * @param {uint8_t} data        数据
  168. * @return {uint8_t}        FAILED        失败
  169. *                                                 SUCCEED        成功
  170. */
  171. uint8_t S_I2C_WriteRegister(I2C_Struct I2C_temp, uint8_t addr, uint8_t regAddr, uint8_t data)
  172. {
  173.         addr <<= 1;
  174.         S_I2C_Start(I2C_temp);
  175.         if(S_I2C_SendByte(I2C_temp, addr) == NACK)
  176.         {
  177.                 S_I2C_Stop(I2C_temp);
  178.                 return FAILED;
  179.         }
  180.         if(S_I2C_SendByte(I2C_temp, regAddr) == NACK)
  181.         {
  182.                 S_I2C_Stop(I2C_temp);
  183.                 return FAILED;
  184.         }
  185.         if(S_I2C_SendByte(I2C_temp, data) == NACK)
  186.         {
  187.                 S_I2C_Stop(I2C_temp);
  188.                 return FAILED;
  189.         }
  190.         S_I2C_Stop(I2C_temp);
  191.         return SUCCEED;
  192. }


  193. /**
  194. * @description:                 读取器件,读取格式:器件读-寄存器地址-读取数据
  195. * @param {I2C_Struct} I2C_temp        I2C_IO结构体
  196. * @param {uint8_t} addr        器件地址(0x00~0x7f)
  197. * @param {uint8_t} regAddr        寄存器地址(0x00~0xff)
  198. * @param {uint8_t} amount        读取数据数量(0x00~0xff)
  199. * @param {uint8_t*} data        返回数据指针
  200. * @param {uint8_t} typ                数据指针类型(由于结构体和数组存储方式不一样,因此需要区分)
  201. *                                                 ARRAY        数组
  202. *                                                 STRUCT        结构体
  203. * @return {*}                        FAILD   读取失败 数据无效
  204. *                                                 SUCCEED 读取成功 数据有效
  205. */
  206. uint8_t S_I2C_ReadRegister(I2C_Struct I2C_temp, uint8_t addr, uint8_t regAddr, uint8_t amount, uint8_t* data, uint8_t typ)
  207. {
  208.         S_I2C_Start(I2C_temp);
  209.         addr = (addr << 1) | 0x01;
  210.         if(S_I2C_SendByte(I2C_temp, addr) == NACK)
  211.         {
  212.                 S_I2C_Stop(I2C_temp);
  213.                 return FAILED;
  214.         }
  215.         if(S_I2C_SendByte(I2C_temp, regAddr) == NACK)
  216.         {
  217.                 S_I2C_Stop(I2C_temp);
  218.                 return FAILED;
  219.         }
  220.         for(amount -= 1;amount;amount --)
  221.         {
  222.                 *data = S_I2C_ReceiveByte(I2C_temp, ACK);
  223.                 if(typ == ARRAY)
  224.                         data ++;
  225.                 else
  226.                         data --;
  227.         }
  228.         *data = S_I2C_ReceiveByte(I2C_temp, NACK);
  229.         S_I2C_Stop(I2C_temp);
  230.         return SUCCEED;
  231. }

  232. /**
  233. * @description:                 读取器件,读取格式:器件写-寄存器地址-器件读-读取数据
  234. * @param {I2C_Struct} I2C_temp        I2C_IO结构体
  235. * @param {uint8_t} addr        器件地址(0x00~0x7f)
  236. * @param {uint8_t} regAddr        寄存器地址(0x00~0xff)
  237. * @param {uint8_t} amount        读取数据数量(0x00~0xff)
  238. * @param {uint8_t*} data        返回数据指针
  239. * @param {uint8_t} typ                数据指针类型(由于结构体和数组存储方式不一样,因此需要区分)
  240. *                                                 ARRAY        数组
  241. *                                                 STRUCT        结构体
  242. * @return {uint8_t}        FAILD   读取失败 数据无效
  243. *                                                 SUCCEED 读取成功 数据有效
  244. */
  245. uint8_t S_I2C_PointerRead(I2C_Struct I2C_temp, uint8_t addr, uint8_t regAddr, uint8_t amount, uint8_t* data, uint8_t typ)
  246. {
  247.         addr <<= 1;
  248.         S_I2C_Start(I2C_temp);
  249.         if(S_I2C_SendByte(I2C_temp, addr) == NACK)
  250.         {
  251.                 S_I2C_Stop(I2C_temp);
  252.                 return FAILED;
  253.         }
  254.         if(S_I2C_SendByte(I2C_temp, regAddr) == NACK)
  255.         {
  256.                 S_I2C_Stop(I2C_temp);
  257.                 return FAILED;
  258.         }
  259.         S_I2C_Stop(I2C_temp);
  260.         
  261.         addr |= 0x01;
  262.         S_I2C_Start(I2C_temp);
  263.         if(S_I2C_SendByte(I2C_temp, addr) == NACK)        //NACK
  264.         {
  265.                 S_I2C_Stop(I2C_temp);
  266.                 return FAILED;
  267.         }
  268.         for(amount -= 1;amount;amount --)
  269.         {
  270.                 *data = S_I2C_ReceiveByte(I2C_temp, ACK);
  271.                 if(typ == ARRAY)
  272.                         data ++;
  273.                 else
  274.                         data --;
  275.         }
  276.         *data = S_I2C_ReceiveByte(I2C_temp, NACK);
  277.         S_I2C_Stop(I2C_temp);
  278.         return SUCCEED;
  279. }
复制代码

使用方法
  1. void main(void)
  2. {
  3.         CLOCK_Init();
  4.         GPIO_Init();
  5.         S_I2C_Init();//初始化结构体,在宏定义中修改引脚等定义
  6.         //接下来就可以调用I2C函数了
  7. }
复制代码

————————————————
版权声明:Vice Versa XL

收藏 评论0 发布时间:2022-10-12 21:32

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版