/*
各位大神,小弟初学ARM9嵌入式编程,想从逻辑程序开始,目前正在学习串口通讯编码。新建了一个工程,
想让PC机与开发板进行串口通讯,用的是UART0,采用非FIFO+中断模式,按照教材和实例初始化了各中断
寄存器、编写了中断服务函数。板子上电后等待PC机发送数据帧,收到后进行响应。运行结果是接收中断
只能响应一次,发送中断正常。各部分代码如下:
//*/
// 1、串口初始化函数:
// 注:
//(1)注释掉的那些寄存器配置不知道是不是一定要加上?
//(2)用的是非FIFO模式,希望通过中断来发送和接收
void Uart_RegInit(void)
{
// configuration GPHCON to UART
//rGPHCON = 0x00faaa;
rGPHCON = rGPHCON & (~(0xf<<4));
//rGPHUP = 0x7ff
rGPHCON = rGPHCON | (0x0a<<4);
// configuration UART0 communication register
// 8-bits,1 stop bit, no parity
rULCON0 = 0x03;
rUCON0 = 0x05;
// configuration UART baudrate
rUBRDIV0 = (int)(PCLK/9600/16) -1;
// clean interrupt bit
rSUBSRCPND = rSUBSRCPND | (0x03);// 0x03:发送和接收 0x02:只能发送 0x01:只能接收
rSRCPND = rSRCPND | (0x01<<28);
rINTPND = rINTPND | (0x01<<28);
// rINTMOD = rINTMOD & (~(0x01<<28));
// rEINTPEND = rEINTPEND | (0x01<<28);
// rEINTMASK = rEINTMASK & (~(0x01<<28)); // 0x03:发送和接收 0x02:只能发送 0x01:只能接收
rINTSUBMSK = rINTSUBMSK & (~(0x03));// UART0总中断
rINTMSK = rINTMSK & (~(0x01<<28));
}
// 2、串口中断函数:
// 注:
//(1)RunMode为在main.c中声明的全局变量,用于控制程序执行逻辑
//(2)我将接收中断和发送中断分开处理了
//(3)接收和发送我都用一个LED灯闪烁了一下
void __irq UART0_interrupt(void)
{
// clean interrupt bit
if(rSUBSRCPND & 0x01)// 接收中断
{
RunMode = 1; // 此处置为1,在main中将程序引导至接收函数Uart_Recv_Byte()
LedModule_TurnOnLed03();
MainModule_Delay(5);
LedModule_TurnOffLed03();
// 0x03:发送和接收 0x02:只能发送 0x01:只能接收
rSUBSRCPND = rSUBSRCPND | (0x01);
// 0x03:发送和接收 0x02:只能发送 0x01:只能接收
rINTSUBMSK = rINTSUBMSK & (~(0x01));
}
else if(rSUBSRCPND & 0x02)// 发送中断
{
LedModule_TurnOnLed04();
MainModule_Delay(5);
LedModule_TurnOffLed04();
// 0x03:发送和接收 0x02:只能发送 0x01:只能接收
rSUBSRCPND = rSUBSRCPND | (0x02);
// 0x03:发送和接收 0x02:只能发送 0x01:只能接收
rINTSUBMSK = rINTSUBMSK & (~(0x02));
}
else
{
// 0x03:发送和接收 0x02:只能发送 0x01:只能接收
RunMode = 1; rSUBSRCPND = rSUBSRCPND | (0x03);
// 0x03:发送和接收 0x02:只能发送 0x01:只能接收
rINTSUBMSK = rINTSUBMSK & (~(0x03));
}
rSRCPND = rSRCPND | (0x01<<28);
rINTPND = rINTPND | (0x01<<28);
//rINTMOD = rINTMOD & (~(0x01<<28));
//rEINTPEND = rEINTPEND | (0x01<<28);
//rEINTMASK = rEINTMASK & (~(0x01<<28));
rINTMSK = rINTMSK & (~(0x01<<28));
}
// 3、main.c中的初始化函数:
void MainModule_Init(void)
{
MMU_Init();
MainModule_SetCpuClk();
MainModule_SetBusClk();
Uart_RegInit();
LedModule_LedXXInit();
MainModule_Timer4Init();
// 串口通讯中断入口
pISR_UART0 = (U32)UART0_interrupt;
// 定时器4中断入口
pISR_TIMER4 = (U32)Timer4_interrupt;
}
// 4、main函数:
void Main(void)
{
int i=0;
int cnt=0;// 用来限制发送中断执行次数
MainModule_Init();
while(1)
{
// 此处应该使用switch,因为功能比较少,懒得编,就先用if凑合着用
// 接收中断发生后,程序会执行到此处,Uart_recv_Byte()用于将数据保存下来
if (RunMode == 1)
{
Uart_Recv_Byte();
RunMode = 2;
}
else if (RunMode == 2)// 数据保存完毕后,原封不动的又发送给pc机
{
Uart_Send_Byte(cnt);
Uart_Send_Byte(0xFF);
for (i=0; i<RxBufPtr; i++)
Uart_Send_Byte(RxDataBuf);
cnt++;
if (cnt<10)// 限制发送10次,不要一直发一直发
RunMode = 2;
else
RunMode = 0;
}
else
;
// 在没有接收和发送时,led01一直闪烁,模拟主程序一直在运行其他功能
LedModule_TurnOnLed01();
MainModule_Delay(1000);
LedModule_TurnOffLed01();
MainModule_Delay(1000);
}
}
// 运行现象总结:
//(1)最初,我将Uart_Recv_Byte()放在中断函数UART0_interrupt()中,也没有区分接收和发送,并且在
// Uart_Recv_Byte()中直接调用Uart_Send_Byte(),意思就是收到PC机发来的数据帧以后立马就响应回去。
// 运行结果是板子上电,led01一直闪烁,led02(使用Timer4中断控制)一直闪烁,此时,板子运行正常。
// 当我从PC机上向开发板发送一帧数据帧后,开发板立刻进行了响应,返回了我刚发下去的数据,但是,此
// 时,问题来了,led01和led02都不再闪烁了,此后PC机和开发板还是可以继续通讯,没有问题,但是led01
// 和led02就永远也没有闪烁了。在网上找了好多帖子,可能是进入UART0_interrupt()后就一直没有恢复现
// 场,所以
// LedModule_TurnOnLed01();
// MainModule_Delay(1000);
// LedModule_TurnOffLed01();
// MainModule_Delay(1000);
// 这段代码和Timer4_interrupt()也都没有再执行。是不是这个原因我也无法确定。
// (2)后来,将Uart_Send_Byte()从Uart_Recv_Byte()中取出来,并且将Uart_Recv_Byte()从
// UART0_interrupt()中取出来,就是上面代码的样子,并且在main_init中将RunMode直接置为2,板子一上
// 电就开始按照设计发送10次数据,然后停止,led01和led02也都正常闪烁。我觉得这个可以说明发送中断
// 确实产生了,而且成功恢复了现场,发送完成后,main中该干啥继续干啥。
// (3)第三阶段,将RunMode置
// 为0,Main函数中就只驱动Led01,Timer04驱动led02,两个灯一直闪烁,没有问题。然后我让PC发送一帧
// 数据,led03闪烁了一下,说明进入了接收中断,然后按照程序设计转到RunMode=2,发送10次数据,此时
// led04也闪烁了,都是正常的,10次发送完成后,led01和led02继续闪烁,没有问题,可是再从PC发送一帧
// 数据下来,接收中断就再也没进去过,main中该干嘛还是继续干嘛,代码就是上面贴出来的样子。
// 反复运行了很多次,并在网上查了很多网友发的帖子,我觉得我的寄存器配置应该没有错,心里一直在思
// 考是不是串口中断属于外部中断,所以还有其他的寄存器没有清,否则为什么只能进一次接收中断呢?其
// 实实现串口发送/接收只是第一步,下一步我想使用Timer4进行接收完成判断。请问各位大神,为什么接收
// 中断就只进去了一次呢?我的代码还有哪里不对?