i2c1从机中断接收发送数据
1、将i2c1设置为从机模式,与树莓派连接。树莓派发送或者读取数据,gd32中断触发,从而接收数据或者向主机发送数据。
2、关于代码的宏定义配置
Application目录的Makefile中 ENABLE_I2C_TEST = yes才会编译I2C1的相关代码。
同时修改i2c.h文件,定义I2C1_MODE为I2C1_MODE_SLAVE,编译烧录后,i2c1即为从机模式。
#define I2C1_MODE I2C1_MODE_SLAVE
3、i2c1从机设置代码,i2c.c中
void i2c1_slave_config(void)
{
/* enable GPIOB clock */
rcu_periph_clock_enable(RCU_GPIOB);
/* enable I2C1 clock */
rcu_periph_clock_enable(RCU_I2C1);
/* connect PB10 to I2C1_SCL */
/* connect PB11 to I2C2_SDA */
gpio_init(GPIOB, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_10 | GPIO_PIN_11);//配置PB10,PB11为复用功能
/* configure I2C clock */
i2c_clock_config(I2C1, I2C1_SPEED, I2C_DTCY_2);
/* configure I2C address */
i2c_mode_addr_config(I2C1, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, I2C1_OWN_ADDRESS7);
/* enable I2C1 */
i2c_enable(I2C1);
/* enable acknowledge */
i2c_ack_config(I2C1, I2C_ACK_ENABLE);
nvic_priority_group_set(NVIC_PRIGROUP_PRE1_SUB3);
nvic_irq_enable(I2C1_EV_IRQn, 0, 2);
nvic_irq_enable(I2C1_ER_IRQn, 0, 1);
/* enable the I2C1 interrupt */
i2c_interrupt_enable(I2C1, I2C_INT_ERR);
i2c_interrupt_enable(I2C1, I2C_INT_BUF);
i2c_interrupt_enable(I2C1, I2C_INT_EV);
}
4、中断处理函数,gd32f30x_it.c中修改
#if I2C1_MODE == I2C1_MODE_SLAVE
/*!
\brief I2C1 event handle function
\param[in] none
\param[out] none
\retval none
*/
void I2C1_EV_IRQHandler(void)
{
I2C1_EventIRQ_Handler();
}
/*!
\brief I2C1 error handle function
\param[in] none
\param[out] none
\retval none
*/
void I2C1_ER_IRQHandler(void)
{
I2C1_ErrorIRQ_Handler();
}
#endif
5、 I2C1_EventIRQ_Handler()、I2C1_ErrorIRQ_Handler() 在i2c.c定义
volatile uint8_t i2c_txbuffer[4] = {0x98,0x78,0x67,0xff};
volatile uint8_t i2c_rxbuffer[128];
volatile uint16_t i2c_rx_num;
volatile uint16_t i2c_tx_num;
static uint8_t isfirst = 0;
static void send_i2c_data(uint8_t *p_buff,uint16_t len)
{
printf("get read command ");
print_register_value(p_buff,len);
}
/*!
\brief handle I2C1 event interrupt request
\param[in] none
\param[out] none
\retval none
*/
void I2C1_EventIRQ_Handler(void)
{
if(i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_ADDSEND)) {
/* clear the ADDSEND bit */
if (isfirst == 0)
{
isfirst = 1;
i2c_rx_num = 0;
}
else
{
isfirst = 0;
i2c_tx_num = 0;
send_i2c_data(i2c_rxbuffer,i2c_rx_num);
}
i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_ADDSEND);
} else if((i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_TBE)) && (!i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_AERR))) {
/* send a data byte */
//printf("now send data %d: \r\n",i2c_tx_num);
i2c_data_transmit(I2C1, i2c_txbuffer[i2c_tx_num++]);
} else if(i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_RBNE)) {
/* if reception data register is not empty ,I2C1 will read a data from I2C_DATA */
i2c_rxbuffer[i2c_rx_num] = i2c_data_receive(I2C1);
i2c_rx_num++;
} else if(i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_STPDET)) {
//printf("get num == %d\r\n",i2c_rx_num);
print_register_value(i2c_rxbuffer,i2c_rx_num);
/* clear the STPDET bit */
i2c_enable(I2C1);
i2c_rx_num = 0;
i2c_tx_num = 0;
isfirst = 0;
}
}
/*!
\brief handle I2C1 error interrupt request
\param[in] none
\param[out] none
\retval none
*/
void I2C1_ErrorIRQ_Handler(void)
{
/* no acknowledge received */
if(i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_AERR)) {
i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_AERR);
}
/* SMBus alert */
if(i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_SMBALT)) {
i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_SMBALT);
}
/* bus timeout in SMBus mode */
if(i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_SMBTO)) {
i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_SMBTO);
}
/* over-run or under-run when SCL stretch is disabled */
if(i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_OUERR)) {
i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_OUERR);
}
/* arbitration lost */
if(i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_LOSTARB)) {
i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_LOSTARB);
}
/* bus error */
if(i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_BERR)) {
i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_BERR);
}
/* CRC value doesn't match */
if(i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_PECERR)) {
i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_PECERR);
}
// /* disable the I2C1 interrupt */
// i2c_interrupt_disable(I2C1, I2C_INT_ERR);
// i2c_interrupt_disable(I2C1, I2C_INT_BUF);
// i2c_interrupt_disable(I2C1, I2C_INT_EV);
}
6、现象,
树莓派发送数据:i2ctransfer -f -y 1 w4@0x18 0x08 0x09 0xA0 0xA3
gd32打印
树莓派读取数据:
i2ctransfer -y -f 1 w3@0x30 0x18 0x19 0x56 r3
发送三个数据读取三个,gd32打印如下:
树莓派读取的数据:
0x98 0x78 0x67是我们定义的数据
volatile uint8_t i2c_txbuffer[4] = {0x98,0x78,0x67,0xff};
7、代码路径:https://gitee.com/xiaoguo-tec_0/gd32-iap-code.git