这个是stm8从机代码
===
#include <Arduino.h>
// #include <stm8s.h> // 假设你使用了STM8标准库
// #include "i2c_slave.h"
#include "Wire.h"
#define I2C_SLAVE_ADDR 0x30
#define I2C_DATA_SIZE 8
#if ((I2C_DATA_SIZE > 0) && ((I2C_DATA_SIZE & (I2C_DATA_SIZE - 1)) != 0))
#error I2C_DATA_SIZE isnt a power of 2.
#endif
#define uint8_bits_def(x) \
union \
{ \
unsigned char x; \
struct \
{ \
unsigned char x##_Bit0 : 1, \
x##_Bit1 : 1, \
x##_Bit2 : 1, \
x##_Bit3 : 1, \
x##_Bit4 : 1, \
x##_Bit5 : 1, \
x##_Bit6 : 1, \
x##_Bit7 : 1; \
}; \
}
uint8_bits_def(tagI2C);
uint8_t i2c_addr = 0;
uint8_t i2c_data[I2C_DATA_SIZE] = {0x00};
int tagI2C_Bit0 = 0;
// // I2C中断服务处理函数声明
// void I2C_ISR(void) __interrupt(19); // I2C中断向量号
void Serial_print(const char *str)
{
while (*str)
{
Serial_write(*str++); // 逐个字符发送
}
}
void I2C_Slave_IRQHandler(void)
{
volatile I2C_Event_TypeDef Event = I2C_GetLastEvent();
Serial_print("STM8 I2C_Slave_IRQHandler.");
/* Slave address matched with the address sent by master */
/* EV1: ADDR = 1, 顺序读SR1,SR3寄存器清除此标志位 */
if (Event == (I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED))
{
tagI2C_Bit0 = 1;
}
/* Slave received the data byte from master */
/* EV2: RxNE = 1, 读DR寄存器清除此位 */
else if (Event == (I2C_EVENT_SLAVE_BYTE_RECEIVED))
{
uint8_t ch = I2C_ReceiveData();
if (tagI2C_Bit0)
{
tagI2C_Bit0 = 0;
i2c_addr = ch;
}
else
{
i2c_data[i2c_addr++ & (I2C_DATA_SIZE - 1)] = ch;
}
}
/* Slave received STOP byte from master */
/* EV4: STOPF = 1,读SR1寄存器后再写CR2清除 */
else if (Event == (I2C_EVENT_SLAVE_STOP_DETECTED))
{
I2C_GetFlagStatus(I2C_FLAG_STOPDETECTION);
I2C_GenerateSTOP(DISABLE);
}
/* SLAVE TRANSMITTER */
/* Data transmited from slave to master */
/* EV3: TxE = 1, 写DR寄存器清除DR */
else if ((Event == (I2C_EVENT_SLAVE_BYTE_TRANSMITTED)) ||
(Event == (I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED)))
{
uint8_t ch = i2c_data[i2c_addr++ & (I2C_DATA_SIZE - 1)];
I2C_SendData(ch);
}
/* Acknowledge failure */
/* EV3-2: AF = 1, AF is cleared by writing '0' in AF bit of SR2 register */
else if (Event == (I2C_EVENT_SLAVE_ACK_FAILURE))
{
I2C_ClearFlag(I2C_FLAG_ACKNOWLEDGEFAILURE);
}
}
// INTERRUPT_HANDLER(I2C_IRQHandler, 19)
// {
// I2C_Slave_IRQHandler();
// }
void I2C_Slave_Init(void)
{
// open I2C clk
CLK_PeripheralClockConfig(CLK_PERIPHERAL_I2C, ENABLE);
I2C_DeInit();
I2C_Init(50000, I2C_SLAVE_ADDR, I2C_DUTYCYCLE_2, I2C_ACK_CURR, I2C_ADDMODE_7BIT, (CLK_GetClockFreq() / 1000000));
/* Enable Error Interrupt*/
I2C_ITConfig((I2C_IT_TypeDef)(I2C_IT_ERR | I2C_IT_EVT | I2C_IT_BUF), ENABLE);
/* enable IIC*/
I2C_Cmd(ENABLE);
// enableInterrupts();
}
void setup()
{
// 初始化串口通信,波特率为9600
Serial_begin(9600);
// 给串口输出一条消息,表示系统已经启动
Serial_print("STM8 initialized and ready.");
I2C_Slave_Init();
// pid_i2c_init();
}
void loop()
{
}
这个是esp32主机代码
===
#include <Arduino.h>
#include "Wire.h"
uint32_t I2C2_SPEED = 50000;
void setup()
{
Serial.begin(115200);
Wire.begin(21, 22, I2C2_SPEED);
}
void loop()
{
byte error, address;
int nDevices = 0;
delay(3000);
Serial.println("Scanning for I2C devices ...");
for (address = 0x01; address < 0x7f; address++)
{
Wire.beginTransmission(address);
// Wire.write(0x11);
error = Wire.endTransmission();
if (error == 0)
{
Serial.printf("I2C device found at address 0x%02X\n", address);
nDevices++;
}
else if (error != 2)
{
Serial.printf("Error %d at address 0x%02X\n", error, address);
}
}
if (nDevices == 0)
{
Serial.println("No I2C devices found");
}
}
esp32 debug:
Scanning for I2C devices ...
I2C device found at address 0x18
Scanning for I2C devices ...
I2C device found at address 0x18
Scanning for I2C devices ...
I2C device found at address 0x18
当esp32扫描到这个i2c地址后stm8会重启,当前不知道是什么原因导致的
|
另外STM8速度通常只有16Mhz,响应中断要尽可能快,所以最好优化中断执行时间,可参考一下例程。
`当esp32扫描到这个i2c地址后stm8会重启,这个重启会是什么原因导致的呢,而且debug一点报错都没有,stm直接是重启了,只要主机扫描到i2c设备从机stm8就重启了
[md]请问下有stm8作为从设备的案例吗
有的,在标准外设库里,注意中断尽可能快些。优先级高。
stm8sfwlib2.31\STM8S_StdPeriph_Lib\Project\STM8S_StdPeriph_Examples\I2C\I2C_TwoBoards\I2C_DataExchange\Slave
我试过这个案例,stm8 作为从机,但是主机一旦扫描到从机的i2c地址后,stm8就会自动重启。如果stm8作为主机的话扫描其它从机则不会出现重启现象,请问这个如何解决呢
这个现象很奇怪,需要调试看看。
1. 可以简化I2C 中断内容,看看是否还会重启。
2. REST 有个状态寄存器,首次上电清零,然后复位后判断输出看看是什么复位标志置位起来的。