最近做一个innovation项目时碰到串口接收中断的问题困扰了好久,终于找到知道原因了。项目用到的芯片是NXPMPC5607B,与一个指纹模块通过串口进行数据传输。在已有的Autosar架构的项目的代码中加入指纹模块代码,另外需要对串口进行正确的配置,才能完成最终的功能。串口接收中断
根据解读芯片手册,配置串口需要先配置SUI端口,PCTL寄存器,然后配置Linflex相关寄存器。因为这款芯片,串口UART和LIN是结合在一起的,因此配置时需要设置UART模式,然后配置波特率等。直接附上串口配置代码:
void LINFlex1_init(uint16_t baudrate)
{
ME.PCTL[49].R = 0x00;
//Configure the input/output TX RX
SIU.PCR[38].R = 0x0600; // Setting PC[6] as LINFlex_1.TxDA
SIU.PCR[39].R = 0x0101; // Setting PC[7] as LINFlex_1.RxDA, pull up
SIU.PSMI[55].B.PADSEL = 0x00; // set PADSEL PC[7] to RXD
//Configure LINFlex1
LINFLEX_1.LINCR1.B.INIT = 1; // request initlization
LINFLEX_1.LINCR1.B.SLEEP = 0; // disable the sleep mode
LINFLEX_1.LINCR1.B.BF = 1; // if Identifier is not comparison with any filter, generate interrupt
LINFLEX_1.UARTCR.B.UART = 1; // enter UART mode
LINFLEX_1.UARTCR.B.WL = 1; // 8 bit data
//LINFLEX_1.UARTCR.B.OP = 1; // even parity
LINFLEX_1.UARTCR.B.PCE = 0; // disable odd and even parity
LINFLEX_1.UARTCR.B.TDFL = 0; // send buffer is only 1 byte
LINFLEX_1.UARTCR.B.RDFL = 0; // receive buffer is only 1 byte
LINFLEX_1.UARTCR.B.RXEN = 1; // enable receive
LINFLEX_1.UARTCR.B.TXEN = 1; // enable transmit
//WKUP.WISR.R = 0x00001000; // setting the wake up event for LINRX1
//WKUP.WRE.R = 0x00000000; //disable the LINRX1 wakeup request
switch (baudrate)
{
case 9600:
{
//baudrate 9600
LINFLEX_1.LINIBRR.B.DIV_M = 833; // Baud Rate = 9600, In Case fipg_clock_lin = 64 MHz
LINFLEX_1.LINFBRR.B.DIV_F = 5; // Baud Rate = 9600, In Case fipg_clock_lin = 64 MHz
}
break;
case 19200:
{
//baudrate 19200
LINFLEX_1.LINIBRR.B.DIV_M = 416; // Baud Rate = 19200, In Case fipg_clock_lin = 64 MHz
LINFLEX_1.LINFBRR.B.DIV_F = 11; // Baud Rate = 19200, In Case fipg_clock_lin = 64 MHz
}
break;
case 38400:
{
//baundrate 38400
LINFLEX_1.LINIBRR.B.DIV_M = 208; // Baud Rate = 38400, In Case fipg_clock_lin = 64 MHz
LINFLEX_1.LINFBRR.B.DIV_F = 5; // Baud Rate = 38400, In Case fipg_clock_lin = 64 MHz
}
break;
case 57600:
{
//baundrate 57600
LINFLEX_1.LINIBRR.B.DIV_M = 138; // Baud Rate = 57600, In Case fipg_clock_lin = 64 MHz
LINFLEX_1.LINFBRR.B.DIV_F = 14; // Baud Rate = 57600, In Case fipg_clock_lin = 64 MHz
}
break;
case 115200:
{
//baundrate 115200
LINFLEX_1.LINIBRR.B.DIV_M = 69; // Baud Rate = 19200, In Case fipg_clock_lin = 64 MHz
LINFLEX_1.LINFBRR.B.DIV_F = 7; // Baud Rate = 19200, In Case fipg_clock_lin = 64 MHz
}
break;
default:
{
//baundrate 57600
LINFLEX_1.LINIBRR.B.DIV_M = 138; // Baud Rate = 57600, In Case fipg_clock_lin = 64 MHz
LINFLEX_1.LINFBRR.B.DIV_F = 14; // Baud Rate = 57600, In Case fipg_clock_lin = 64 MHz
}
break;
}
LINFLEX_1.LINIER.B.DRIE = 1; // enable the receive interrupt
LINFLEX_1.UARTSR.B.DRF = 1; // clear the receive data complete flag
LINFLEX_1.UARTSR.B.DTF = 1; // clear the transmit data complete flag
//INTC.PSR[99].R = 0x01; // set the interrupt priority as 1
LINFLEX_1.LINCR1.B.INIT = 0; // change to normal mode
}
串口初始化结束后,接着是编写中断函数,中断函数非常简单,就是从寄存器中读取接受的数据存到一个数据缓存arrar_uart[]中,接收完需要清除接收完成标志位DRF。
void UART1_ISRfunc(void)
{
arrar_uart[length_uart++] = (uint8_t)LINFLEX_1.BDRM.R;
LINFLEX_1.UARTSR.B.DRF = 1;
}
中断函数编写完后,需要配置串口函数在中断向量表中的入口地址。设置如下:
__asm(" e_lis r0,%hi( UART1_ISR_cat2c)");
__asm(" e_or2i r0,%lo( UART1_ISR_cat2c)");
设置中断函数的入口地址,由于中断函数在osek任务调度同一管理,下面的UART1_ISR_cat2c即是osek中的中断函数,此处可以直接替换成中断函数UART1_ISRfunc。
尤其要注意的是设置中断优先级的这段
__asm(" e_add16i r31, r31, 26"); /* prio 1 for UART1_ISR */
__asm(" e_add16i r30, r30, 0");
__asm(" e_stb r30, 0(r31)");
否则中断会被其他的中断抢占,而导致进不了中断函数,在调试过程中,之前代码没有设置优先级,从而导致中断函数一直进不去。