硬件IIC的主从中断在582的最新EVT中已支持。
对于IIC从机中断,例程中已封装好中断处理过程,用户调用app_i2c时,初始化中需要配置回调函数。
初始化的配置如下。
struct i2c\_slave\_cb slave\_user = { //配置回调结构体
.on\_receive = i2c\_on\_slave\_receive\_user,
.on\_transmit = i2c\_on\_slave\_transmit\_user,
};
i2c\_app\_init(RxAdderss); //IIC硬件模块的初始化及软件标志的初始化
i2c\_slave\_cb\_register(&slave\_user); //注册回调
默认回调函数如下。
static void i2c_on_slave_transmit_user(uint8_t *data, uint8_t *len)
{
*len = sizeof(TxData);
memcpy(data, TxData, sizeof(TxData));
}
static void i2c_on_slave_receive_user(uint8_t *data, uint8_t len)
{
PRINT("I2C slave receiver callback: received (");
for(int i = 0; i < len; i++) {
PRINT(" %#x", data[i]);
}
PRINT(" )\n");
}
若需要串口打印日志,可以在工程预编译中增加宏CONFIG_I2C_DEBUG。
接下来以注释的方式解析一下中断服务函数中做了哪些处理。
__INTERRUPT
__HIGH_CODE
void I2C_IRQHandler(void)
{
uint32_t event = I2C_GetLastEvent();
print_i2c_irq_sta(event);
/\* I2C Master \*/
if (event & (RB\_I2C\_MSL << 16)) { //判断为主机模式
if (event & RB\_I2C\_SB) { //判断主机模式已发送起始信号
/\* Start condition sent, send address \*/
I2C\_SendData(i2c\_slave\_addr\_rw); //写从地址到数据寄存器后,SB位会自动清除
I2C\_DBG("Master selected, send address\\n");
}
/\* I2C Master transmitter \*/
if (event & (RB\_I2C\_TRA << 16)) { //判断是主机的发送模式
I2C\_DBG("Master transmitter:\\n");
/\* Slave receiver acked address or sent bit \*/
if (event & (RB\_I2C\_ADDR | RB\_I2C\_BTF | RB\_I2C\_TxE | (RB\_I2C\_TRA << 16))) {
/\* if there is data to send, send it, otherwise stop \*/
if (i2c\_master\_buffer\_index < i2c\_master\_buffer\_length) { //判断待发送数据还没发完
I2C\_SendData(i2c\_master\_buffer\[i2c\_master\_buffer\_index++\]);
I2C\_DBG(" send (%#x)\\n",
i2c\_master\_buffer\[i2c\_master\_buffer\_index - 1\]);
} else {
if (i2c\_send\_stop) { //判断数据发完了,如果允许产生停止位则产生停止位
i2c\_state = I2C\_READY;
I2C\_GenerateSTOP(ENABLE); //产生停止位
I2C\_DBG(" send STOP\\n");
} else {
i2c\_in\_repstart = true; //置标志表示即将重起始
/\* we're gonna send the START, don't enable the interrupt. \*/
I2C\_ITConfig(I2C\_IT\_BUF, DISABLE);
I2C\_ITConfig(I2C\_IT\_EVT, DISABLE);
I2C\_ITConfig(I2C\_IT\_ERR, DISABLE);
I2C\_GenerateSTART(ENABLE);
i2c\_state = I2C\_READY;
I2C\_DBG(" restart\\n");
}
}
}
/\* Address or data sent, nack received \*/
if (event & RB\_I2C\_AF) { //地址/数据发送后应答失败
I2C\_ClearFlag(I2C\_FLAG\_AF); //清标志
i2c\_error = I2C\_MT\_NACK; //置主机发送接收错误标志
i2c\_state = I2C\_READY; //发送停止信号停止帧传输
I2C\_GenerateSTOP(ENABLE); //产生停止信号
I2C\_DBG(" NACK received, sent stop\\n");
}
} else { //判断为主机的接收模式
/\* I2C Master reveiver \*/
I2C\_DBG("Master receiver:\\n");
/\* address sent, ack received \*/
if(event & RB\_I2C\_ADDR) { //主机成功设置了从机的地址
/\* ack if more bytes are expected, otherwise nack \*/
if (i2c\_master\_buffer\_length) { //判断接下来需要接收多少字节,如果需要接收多个字节,就置自动回ACK
//注意这里判断条件,在1.8的583EVT与之前的EVT不同,以这里的为准。
I2C_AcknowledgeConfig(ENABLE);
I2C_DBG(" address sent\n");
I2C_DBG(" ACK next\n");
} else { //判断接下来只接收一个字节,关闭自动回ACK即自动回NACK
//XXX: Should not delay too match before NACK
I2C_AcknowledgeConfig(DISABLE);
is_nack_sent = true; //置标志,数据接收时做具体处理
I2C_DBG(" address sent\n");
I2C_DBG(" NACK next\n");
}
}
/\* data reveived \*/
if (event & (RB\_I2C\_RxNE)) { //接收数据寄存器内非空,即收到数据
/\* put byte into buffer \*/
i2c\_master\_buffer\[i2c\_master\_buffer\_index++\] = I2C\_ReceiveData(); //接收数据到buffer中
if (i2c\_master\_buffer\_index < i2c\_master\_buffer\_length) { //判断接下来是否为期望接收的最后一个字节
I2C\_AcknowledgeConfig(ENABLE); //接下来不是最后一个字节,接收应答设置为自动回ACK
I2C\_DBG(" ACK next\\n");
} else {
//XXX: Should not delay too match before NACK
I2C\_AcknowledgeConfig(DISABLE); //连续读倒数最后一个字节前将接收应答ACK关闭,即最后一个字节后自动回NACK
I2C\_DBG(" NACK next\\n");
if (is\_nack\_sent) { //如果已设置最后一个字节前置了接收应答NACK
is\_nack\_sent = false; //清标志
if (i2c\_send\_stop) {
I2C\_GenerateSTOP(ENABLE);
i2c\_state = I2C\_READY;
I2C\_DBG(" send STOP\\n");
} else {
i2c\_in\_repstart = true; //写完了从机内的目标寄存器,发重起始信号
/\* we're gonna send the START, don't enable the interrupt. \*/
I2C\_ITConfig(I2C\_IT\_BUF, DISABLE);
I2C\_ITConfig(I2C\_IT\_EVT, DISABLE);
I2C\_ITConfig(I2C\_IT\_ERR, DISABLE);
I2C\_GenerateSTART(ENABLE);
i2c\_state = I2C\_READY;
I2C\_DBG(" restart\\n");
}
} else {
is\_nack\_sent = true; //没有要求
}
}
I2C\_DBG(" received data (%#x)\\n",
i2c\_master\_buffer\[i2c\_master\_buffer\_index - 1\]);
}
/\* nack received \*/
if (event & RB\_I2C\_AF) { //主机接收模式最后一个字节后为NACK
I2C\_ClearFlag(I2C\_FLAG\_AF);
/\* put final byte into buffer \*/
i2c\_master\_buffer\[i2c\_master\_buffer\_index++\] = I2C\_ReceiveData(); //收下最后一个字节的数据
if (i2c\_send\_stop) { //判断读完之后是停止信号还是重起始信号
i2c\_state = I2C\_READY;
I2C\_GenerateSTOP(ENABLE);
I2C\_DBG(" NACK received, send STOP\\n");
} else {
i2c\_in\_repstart = true; //读完后不停止,会产生重起始信号以衔接后续操作
/\* we're gonna send the START, don't enable the interrupt. \*/
I2C\_ITConfig(I2C\_IT\_BUF, DISABLE);
I2C\_ITConfig(I2C\_IT\_EVT, DISABLE);
I2C\_ITConfig(I2C\_IT\_ERR, DISABLE);
I2C\_GenerateSTART(ENABLE);
i2c\_state = I2C\_READY;
I2C\_DBG(" restart\\n");
}
}
}
} else { //判断为从机模式
/\* I2C slave \*/
/\* addressed, returned ack \*/
if (event & RB\_I2C\_ADDR) { //地址匹配,接下来判断方向
if (event & ((RB\_I2C\_TRA << 16) | RB\_I2C\_TxE)) { //判断从机发送方向匹配或者发送方向寄存器空,那么接下来需要发送数据 //发送方向寄存器空需要判断吗?
I2C\_DBG("Slave transmitter address matched\\n");
i2c\_state = I2C\_STX;
i2c\_slave\_txbuffer\_index = 0;
i2c\_slave\_txbuffer\_length = 0;
if (slave\_cb && slave\_cb->on\_transmit) { //如果注册了回调,就按照回调函数,将数据拷贝到i2c\_slave\_txbuffer中
slave\_cb->on\_transmit(i2c\_slave\_txbuffer, &i2c\_slave\_txbuffer\_length);
}
} else { //判断从机接收方向地址匹配,那么接下来需要接收数据
I2C\_DBG("Slave reveiver address matched\\n");
i2c\_state = I2C\_SRX;
i2c\_slave\_rxbuffer\_index = 0;
}
}
if (event & (RB\_I2C\_TRA << 16)) { //从机发送
/\* Slave transmintter \*/
I2C\_AcknowledgeConfig(ENABLE); //预设自动回复ACK
I2C\_DBG("Slave transmitter:\\n");
if (event & RB\_I2C\_AF) { //收到了NACK,发送失败
/\* Nack received \*/
I2C\_ClearFlag(I2C\_FLAG\_AF); //清除应答失败标志
I2C\_AcknowledgeConfig(ENABLE); //预设自动回复ACK
I2C\_DBG(" Nack received\\n");
/\* leave slave receiver state \*/
i2c\_state = I2C\_READY;
/\* clear status \*/
event = 0;
}
if(event & (RB\_I2C\_BTF | RB\_I2C\_TxE)) { //字节发送结束或者发送方向寄存器空
/\* copy data to output register \*/
I2C\_SendData(i2c\_slave\_txbuffer\[i2c\_slave\_txbuffer\_index++\]); //逐字节发送数据
/\* if there is more to send, ack, otherwise nack \*/
if (i2c\_slave\_txbuffer\_index < i2c\_slave\_txbuffer\_length) {
I2C\_AcknowledgeConfig(ENABLE); //预设自动回复ACK
}else{
I2C\_AcknowledgeConfig(DISABLE); //预设自动回复NACK
}
I2C\_DBG(" send (%#x)\\n",
i2c\_slave\_txbuffer\[i2c\_slave\_txbuffer\_index - 1\]);
}
} else { //从机接收
/\* Slave receiver \*/
I2C\_DBG("Slave receiver:\\n");
if (event & RB\_I2C\_RxNE) { //判断非空即收到了数据
/\* if there is still room in the rx buffer \*/
//判断还有没有缓存空间,如果仍有空间就接收数据并回ACK,没有更多空间了就回NACK
if (i2c\_slave\_rxbuffer\_index < I2C\_BUFFER\_LENGTH) {
/\* put byte in buffer and ack \*/
i2c\_slave\_rxbuffer\[i2c\_slave\_rxbuffer\_index++\] = I2C\_ReceiveData();
I2C\_AcknowledgeConfig(ENABLE);
I2C\_DBG(" received (%#x)\\n",
i2c\_slave\_rxbuffer\[i2c\_slave\_rxbuffer\_index - 1\]);
} else {
// otherwise nack
I2C\_AcknowledgeConfig(DISABLE);
}
}
if (event & RB\_I2C\_STOPF) { //从机接收模式下收到停止位,清标志,清数组下标索引
/\* ack future responses and leave slave receiver state \*/
R16\_I2C\_CTRL1 |= RB\_I2C\_PE; //clear flag
I2C\_DBG(" reveive stop\\n");
/\* callback to user defined callback \*/
if (slave\_cb && slave\_cb->on\_receive) {
slave\_cb->on\_receive(i2c\_slave\_rxbuffer, i2c\_slave\_rxbuffer\_index);
}
/\* since we submit rx buffer , we can reset it \*/
i2c\_slave\_rxbuffer\_index = 0;
}
if (event & RB\_I2C\_AF) { //如果接收模式中接收到了NACK,清标志,预设自动回复ACK
I2C\_ClearFlag(I2C\_FLAG\_AF);
/\* ack future responses \*/
I2C\_AcknowledgeConfig(ENABLE);
}
}
}
if(event & RB\_I2C\_BERR){ //总线错误
I2C\_ClearFlag(RB\_I2C\_BERR);
I2C\_GenerateSTOP(ENABLE);
i2c\_error = I2C\_BUS\_ERROR;
I2C\_DBG("RB\_I2C\_BERR\\n");
}
if(event & RB\_I2C\_ARLO){ //仲裁丢失错误
I2C\_ClearFlag(RB\_I2C\_ARLO);
i2c\_error = I2C\_ARB\_LOST;
I2C\_DBG("RB\_I2C\_ARLO\\n");
}
I2C\_DBG("\\n");
}
手机扫一扫
移动阅读更方便
你可能感兴趣的文章