当前位置: 首页 > news >正文

STM32设置为I2C从机模式(转)

测试例程:定义一个256字节的buffer用来存放I2C从机的数据,默认赋初值0-255,然后通过中断的方式实现I2C数据读写。
示例代码如下:

  1 #include "stm32f10x.h"
  2 #include "stm32f10x_gpio.h"
  3 #include "stm32f10x_rcc.h"
  4 #include "stm32f10x_i2c.h"
  5 #include "misc.h"
  6 
  7 #define I2CSLAVE_ADDR           0x40 << 1  // address is 0x40
  8 
  9 #define I2C1_CLOCK_FRQ          100000     // I2C-Frq in Hz (100 kHz)
 10 #define I2C1_RAM_SIZE           256        // RAM Size in Byte
 11 
 12 #define I2C1_MODE_WAITING       0          // Waiting for commands
 13 #define I2C1_MODE_SLAVE_ADR_WR  1          // Received slave address (writing)
 14 #define I2C1_MODE_ADR_BYTE      2          // Received ADR byte
 15 #define I2C1_MODE_DATA_BYTE_WR  3          // Data byte (writing)
 16 #define I2C1_MODE_SLAVE_ADR_RD  4          // Received slave address (to read)
 17 #define I2C1_MODE_DATA_BYTE_RD  5          // Data byte (to read)
 18 
 19 uint8_t i2c1_mode = I2C1_MODE_WAITING;
 20 uint8_t i2c1_ram_adr = 0;
 21 uint8_t i2c1_ram[I2C1_RAM_SIZE];
 22 
 23 uint8_t Get_I2C1_Ram(uint8_t adr) 
 24 {
 25     return i2c1_ram[adr];
 26 }
 27 
 28 void Set_I2C1_Ram(uint8_t adr, uint8_t val) 
 29 {
 30     i2c1_ram[adr] = val;
 31     return;
 32 }
 33 
 34 void I2C1_Ram_Init(void) 
 35 {
 36     uint16_t i;
 37     for (i = 0; i < 256; i++)
 38     {
 39         Set_I2C1_Ram(i, i);
 40     }
 41 }
 42 
 43 void I2C1_Slave_Init(void) 
 44 {
 45     GPIO_InitTypeDef  GPIO_InitStructure;
 46     NVIC_InitTypeDef NVIC_InitStructure;
 47     I2C_InitTypeDef  I2C_InitStructure;
 48 
 49     RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
 50     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
 51     RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
 52 
 53     /* Configure I2C_EE pins: SCL and SDA */
 54     GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6 | GPIO_Pin_7;
 55     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 56     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
 57     GPIO_Init(GPIOB, &GPIO_InitStructure);
 58 
 59     /* Configure the I2C event priority */
 60     NVIC_InitStructure.NVIC_IRQChannel                   = I2C1_EV_IRQn;
 61     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
 62     NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0;
 63     NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
 64     NVIC_Init(&NVIC_InitStructure);
 65 
 66     /* Configure I2C error interrupt to have the higher priority */
 67     NVIC_InitStructure.NVIC_IRQChannel = I2C1_ER_IRQn;
 68     NVIC_Init(&NVIC_InitStructure);
 69 
 70     /* I2C configuration */
 71     I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
 72     I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
 73     I2C_InitStructure.I2C_OwnAddress1 = I2CSLAVE_ADDR;
 74     I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
 75     I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
 76     I2C_InitStructure.I2C_ClockSpeed = I2C1_CLOCK_FRQ;
 77 
 78     /* I2C Peripheral Enable */
 79     I2C_Cmd(I2C1, ENABLE);
 80 
 81     /* Apply I2C configuration after enabling it */
 82     I2C_Init(I2C1, &I2C_InitStructure);
 83 
 84     I2C_ITConfig(I2C1, I2C_IT_EVT, ENABLE); //Part of the STM32 I2C driver
 85     I2C_ITConfig(I2C1, I2C_IT_BUF, ENABLE);
 86     I2C_ITConfig(I2C1, I2C_IT_ERR, ENABLE); //Part of the STM32 I2C driver
 87 
 88     I2C1_Ram_Init();
 89 }
 90 
 91 void I2C1_ClearFlag(void) 
 92 {
 93     /* ADDR Flag clear */
 94     while((I2C1->SR1 & I2C_SR1_ADDR) == I2C_SR1_ADDR) 
 95     {
 96         I2C1->SR1;
 97         I2C1->SR2;
 98     }
 99 
100     /* STOPF Flag clear */
101     while((I2C1->SR1&I2C_SR1_STOPF) == I2C_SR1_STOPF) 
102     {
103         I2C1->SR1;
104         I2C1->CR1 |= 0x1;
105     }
106 }
107 
108 void I2C1_EV_IRQHandler(void) 
109 {
110     uint8_t wert;
111     uint32_t event;
112 
113     /* Reading last event */
114     event = I2C_GetLastEvent(I2C1);
115 
116     /* Event handle */
117     if(event == I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED) 
118     {
119         // Master has sent the slave address to send data to the slave
120         i2c1_mode = I2C1_MODE_SLAVE_ADR_WR;
121     }
122     else if(event == I2C_EVENT_SLAVE_BYTE_RECEIVED) 
123     {
124         // Master has sent a byte to the slave
125         wert = I2C_ReceiveData(I2C1);
126         // Check address
127         if(i2c1_mode == I2C1_MODE_SLAVE_ADR_WR) 
128         {
129             i2c1_mode = I2C1_MODE_ADR_BYTE;
130             // Set current ram address
131             i2c1_ram_adr = wert;
132         }
133         else 
134         {
135             i2c1_mode = I2C1_MODE_DATA_BYTE_WR;
136             // Store data in RAM
137             Set_I2C1_Ram(i2c1_ram_adr, wert);
138             // Next ram adress
139             i2c1_ram_adr++;
140         }
141     }
142     else if(event == I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED) 
143     {
144         // Master has sent the slave address to read data from the slave
145         i2c1_mode = I2C1_MODE_SLAVE_ADR_RD;
146         // Read data from RAM
147         wert = Get_I2C1_Ram(i2c1_ram_adr);
148         // Send data to the master
149         I2C_SendData(I2C1, wert);
150         // Next ram adress
151         i2c1_ram_adr++;
152     }
153     else if(event == I2C_EVENT_SLAVE_BYTE_TRANSMITTED) 
154     {
155         // Master wants to read another byte of data from the slave
156         i2c1_mode = I2C1_MODE_DATA_BYTE_RD;
157         // Read data from RAM
158         wert = Get_I2C1_Ram(i2c1_ram_adr);
159         // Send data to the master
160         I2C_SendData(I2C1, wert);
161         // Next ram adress
162         i2c1_ram_adr++;
163     }
164     else if(event == I2C_EVENT_SLAVE_STOP_DETECTED) 
165     {
166         // Master has STOP sent
167         I2C1_ClearFlag();
168         i2c1_mode = I2C1_MODE_WAITING;
169     }
170 }
171 
172 void I2C1_ER_IRQHandler(void) 
173 {
174     if (I2C_GetITStatus(I2C1, I2C_IT_AF)) 
175     {
176         I2C_ClearITPendingBit(I2C1, I2C_IT_AF);
177     }
178 }

4 总结
通过上位机工具的测试以及逻辑分析仪的解析,STM32的硬件I2C从机通信正常且稳定,读写速度测试了100k和400k,没有发现问题,至此测试完成。
好了,关于STM32如何设置从机模式就介绍到这里,如果你们有什么问题,欢迎评论区留言。

需要完整源码工程的同学可以自行下载:源码下载地址
另外还有一篇HAL库版本的博客:STM32设置为I2C从机模式(HAL库版本)

http://www.jsqmd.com/news/67628/

相关文章:

  • Linux Mint在更新内核后出现网卡未识别的问题
  • jittor和torch的爱恨情仇
  • FeatherNotes
  • XHORSE XSGA80EN Universal Smart Key 5pcs/lot – Ideal for European American Car Owners Mechanics
  • P1036 选数
  • GIT-01 Fuel Injection Drivebox Injector Tester: Universal Plugs for All Injectors + Frequency Lock
  • 虚拟机 VMware Tools 工具安装失败/缺失的问题
  • AgileConfig-1.11.0 发布:增强的权限管理
  • Windows 10 终止服务,趁微软官方下载通道还没有关闭,现在教大家如何用电脑浏览器下载。
  • CSAPP 存储器层次结构
  • WPS免费版(会员功能永久可用)
  • P1030 求先序序列
  • 2025年真空滚揉机厂家口碑排行:本地用户真实体验分享,市场上专业的滚揉机品牌优质企业盘点及核心优势详细解读
  • 第49天(中等题 数据结构)
  • 谷歌反重力 Google Antigravity 常见问题
  • windows11同时安装mysql8和mysql5.7数据库
  • 2025年午餐肉罐头机优质生产商口碑榜发布,行业内罐头机产品博锐发展迅速,实力雄厚
  • 每日反思(2025年12月8日)
  • JavaEE 和 JavaWeb的关系
  • 倍增
  • pwn入门记录
  • 2025-12-9
  • Maven 下载 Spigot 依赖失败问题排查:Could not find artifact org.spigotmc:spigot-api…
  • 12.8每日总结
  • 2025/12/08 分享
  • frp
  • 深刻理解HTTP和RPC的区别
  • linux 中 socket 文件是什么?和 socket 编程有什么关系?和 TCP/IP 协议栈又有什么关系?
  • 智能座舱的下一站:从“车内大屏”到“全域协同” - 智慧园区
  • 硬件电子知识(基础篇)