This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
MSP430FR5738 I2C DMA 模式调试时碰到了一个问题,貌似是430单片机的bug,问题描述如下
1、P1.6/1.7配置成I2C Slave 通信模式,I2C Slave RX 和Slave TX配置成DMA模式,配置代码如下
由于I2C 接受数据时,事先并不知道接收长度,在DMA接收时,当STOP信号到来时,表示一帧数据的结束。
当STOP信号到来时,结束当前DMA传输
1. I2C Config
void I2C_Slave_Init(unsigned char address)
{
UCB0CTLW0 |= UCSWRST; //reset I2C Module
UCB0CTLW0 |= UCMODE_3 + UCSYNC; //I2C Slave
UCB0CTLW1 &= ~USCI_I2C_UCCLTOIFG;
UCB0CTLW1 |= (0x01 << 6);
UCB0I2COA0 = address + UCOAEN; //I2C ADDRESS
//Set P1.6 & P1.7 on I2C MODE
P1SEL1 |= BIT6 + BIT7;
P1SEL0 &= ~BIT6;
P1SEL0 &= ~BIT7;
UCB0CTLW0 &= ~UCSWRST; //release reset I2C Module
UCB0IE__I2C |= UCSTPIE;//Enable I2C INTERRUPT
}
2、I2C Slave RX DMA config
void I2C_Slave_RX_DMA_Config()
{
DMA0CTL =
(0x00 << 12) //Single Transfer
|(0x03 << 10) //Dest Inc
|(0x00 << 8) //Src Unchange
|(0x01 << 7)
|(0x01 << 6);
DMA0SA = (unsigned int)&UCB0RXBUF;
DMA0DA = (unsigned int)buf;
DMA0SZ = 40;
DMACTL0 |= 18;//MSP430FR5738 I2C Slave RX Trigger
DMA0CTL |= DMAIE;
DMA0CTL |= DMAEN;
}
3、中断
switch(__even_in_range(UCB0IV,0x1E))
{
case 0x08:
if(UCB0CTLW0_bit.UCTR == 0) //Receive
{
DMA I2C Slave RX ReConfig
}
else //Transmitter
{
DMA I2C Slave TX ReConfig
}
UCB0IFG = 0;
break;
default:
break;
}
main()
{
.....
I2C_Slave_Init();
I2C_Slave_RX_DMA_Config();
_EINT();
while(1)
{
...
....
//P2DIR_bit.P2DIR2 = 1;
}
}
问题
如果在while(1)的循环里涉及到单片机IO寄存器的配置,操作,则 I2C Slave RX DMA接收就会出问题,表现目前监测到两种情况,一种就是没有识别STOP信号,无中断产生,另一种是中断IFG标志已产生,但没有进中断服务程序,如果此时在仿真器中暂停一次,再全速运行,则可以进中断服务程序
如果while(1)里没有对IO端口的操作,则整个I2C Slave RX DMA 没有任何问题
对IO端口寄存器配置操作,不会影响I2C Slave TX DMA
你好
首先有一些代码上的建议
1. 清除USCI_I2C_UCCLTOIFG 标志位应该是在UCB0IFG 寄存器中
2. UCB0CTLW1 |= (0x01 << 6); 你是打算使能 Clock low timeout 对吧?
3. 对于DMA 源地址和目的地址的配置请参照我们的参考历程dev.ti.com/.../node
为了我们能更快的定位问题, 可以提供一个完整的CCS 或IAR 的可以复现问题的最简工程吗? 最好附上Host 端的代码如果Host 也是MSP430
因为这个程序,I2C的工作模式是Slave 模式,所以所有的读写发起都是由另外的Master发起的,
Slave TX DMA和RX DMA都是配置好了,如果外部有Write操作,则Slave RX会接收数据,Stop来的时候,表示一包数据结束,而外部有Read操作的时候,Slave TxDMA会工作,将txbuf里的数据发出去,Stop到的时候,表示一包数据读操作结束。
因此不管是TX还是RX,最终都会产生Stop信号,但两者在程序中的处理是不一样的,所以需要在Stop中断里判断是READ还是WRITE的中断,以做出不同的处理。
我想做的就是一个I2C Slave 模式,可以正常收发数据。以前是用的非DMA模式操作的,这个对I2C通信来说,没有问题。但由于我需要处理的一部分工作对时间特别敏感,因此在I2C读写操作时,非DMA模式,会频繁的进中断,每收到或发出一个字节就要进一次中断,这个时间会影响程序的部分功能,所以我就想切换成DMA模式,只在Stop到来时集中处理一次中断,那我在程序中可以把这个因素处理掉,所以我才想换成DMA模式的
现在的问题是,主程序循环中只要不涉及到IO端口的操作,I2C的所有功能都是正常的,但主循环中如果涉及到对端口寄存器的配置,就会影响I2C的通信(主要影响I2C slave RX模式,即主机WRITE的时候会出错,主机READ,即Slave DMA TX模式目前没有错误),对IO端口操作越频繁就越容易报错,主要的I2C错误目前发现两种,一种就是识别不到STOP中断,所以I2C 模块的状态机就在Busy态出不来,还有一种状态从仿真看,是识别到了STOP中断的,但就是不进中断服务程序,如果此时在仿真器按暂停,就发现IFG是置位了的,中断后再全速运行,又是可以进中断服务程序的。这个我在主贴里已经描述过了。
上面就是我目前发现的问题。
你好
这个问题是由于DMA7 引起的。
指令
P2DIR_bit.P2DIR0 = 1;
P2OUT_bit.P2OUT0 = 1;
P2OUT_bit.P2OUT0 = 0;
经编译后均为 BIS.B 或BIC.B 这些都是 read-modify-write instruction,当CPU 执行这些指令时如何产生DMA请求,CPU 会miss 下一个中断。
解决方法也很简单
避免使用read-modify-write instruction。 比如要将P2OUT 的BIT0 置位可以这样操作:定义一个中间变量buffer, buffer=P2OUT; 然后 P2OUT=buffer|BIT0;