一、环境准备
电脑系统:Windows 10 专业版 22H2
IDE:VScode
测试硬件:AG32VF407
二、测试步骤
1、测试目的
串口功能逐步实现吧
2、查询模式
example_uart_rcvIqr.c: (访问密码: 1666)
①将文件移植到src文件夹下,放其他文件夹可能要指定头文件路径。
②在example.h中声明TestUart_simple,需要在main中调用
③编译调试
图示串口助手发送2次,才回应,测试发现是单帧固定12字节,才立马回应,不是很符合要求,需求是不定长才行
④修改工程代码
简单工程可以这样做,有阻塞延时等,估计就做不了了,感觉开启FIFO缓存,可能还要好些。
example_uart_查询.rar: (访问密码: 1666)
3、接收中断模式
example_uart_rcvIqr.c: (访问密码: 1666)
①将文件移植到src文件夹下,放其他文件夹可能要指定头文件路径。
②在example.h中声明TestUart_rcvIrq,需要在main中调用
③编译调试
发现此demo只能单帧发送8字节,才能完成一次中断触发,或者说是每8字节触发一次中断。
需要注意一个调试bug,发送大于16字节数据,单帧连续触发2次中断,仿真模式下,可能不在触发中断了,但其他功能正常运行。可能是调试模式兼容问题,暂时没找到原因,避开就行。
④结合手册后发现,是启用了FIFO导致的,工程中启用的FIFO。
⑤修改工程代码
UART_Init初始化内设置UART_LCR_FIFO_1;
屏蔽UART_SetRxIntFifoLevel;
将中断内改为,接收一字节,就立马发送一字节;
屏蔽isRecv,避免下方while循环内再次发送;
⑥编译调试
达到预期
example_uart_接收中断.rar: (访问密码: 1666)
4、空闲中断
example_uart_rxIdleIrq.c: (访问密码: 1666)
①将文件移植到src文件夹下,放其他文件夹可能要指定头文件路径。
②修改example.c、example.h文件
③由于使用uart0测试,故需要注意检测ve文件,修改链接信息
④编译并测试
满足我的需求,基本不用怎么改,估计就把发送函数移植到空闲中断就可以了
⑤大致原理
//1、初始化串口,并开启FIFO
UART_Init(UART0, 115200, UART_LCR_DATABITS_8, UART_LCR_STOPBITS_1, UART_LCR_PARITY_NONE, UART_LCR_FIFO_16);
//2、开启接收中断、超时中断,定义FIFO缓存,每满一半时,触发一次接收中断。
UART_EnableInt(UART0, UART_INT_RT); //配置 收超时中断
UART_EnableInt(UART0, UART_INT_RX); //配置 收中断
UART_SetRxIntFifoLevel(UART0, UART_INT_FIFO_HALF); //配置FIFO收多少字节时产生收中断
INT_EnableIRQ(UART0_IRQn, UART_PRIORITY);
//3、触发接收中断,说明FIFO中数据超过一半了,此时读取7字节,留一个字节给空闲中断或者下次接收中断。
//这里有个不是bug的bug的,如果在接收中断中一次将FIFO数据都读取了,那么就不会触发空闲中断。
//所以如果接收中断一次读取8字节,而刚好也发送8字节,那么接收中断读取后,FIFO中为空,空闲中断不会触发,也就不会发送数据了
void UART0_isr()
{
if (UART_IsRawIntActive(UART0, UART_INT_RX)) {
UART_ClearInt(UART0, UART_INT_RX);
//注意:这时FIFO里有8个字节长度,但特意不全部收取。
//这么做,是为了保证传输数据刚好是8的整数倍时,仍然会触发下边的UART_INT_RT中断。
UART_Receive(UART0, rxbuf + rcvLen, 7, 0); //half: 16/2=8。
rcvLen += 7;
}
else if (UART_IsRawIntActive(UART0, UART_INT_RT)) {
UART_ClearInt(UART0, UART_INT_RT);
rcvLen += UART_Receive(UART0, rxbuf + rcvLen, 8, 1); //最后一个参数不能为0,为0时UART_Receive是不会超时退出的
UART_Send(UART0, rxbuf, rcvLen);
rcvLen = 0;
//isRecvEnd = 1; //idle一包收满
}
}
example_uart_空闲中断.rar: (访问密码: 1666)
5、DMA通讯
example_uart_dmaIrq.c: (访问密码: 1666)
依照上例移植文件,示例采用的是DMA中断,需要大于等于设定个数才能触发DMA中断。
添加写函数(不简洁,应该有其他写法)
void TestUartDMASend(char * data,int dataLen)
{
//set tx dma
DMAC_Config(DMAC_CHANNEL0, (uint32_t)data, (uint32_t)&UART1->DR,
DMAC_ADDR_INCR_ON, DMAC_ADDR_INCR_OFF,
DMAC_WIDTH_8_BIT, DMAC_WIDTH_8_BIT,
DMAC_BURST_1, DMAC_BURST_1,
dataLen, DMAC_MEM_TO_PERIPHERAL_DMA_CTRL,
0, UART1_TX_DMA_REQ);
}
尝试DMA+空闲中断,没成功啊,有成功的教教我哈
例程中通过宏定义区分了可以参考。
example_uart_DMA.rar: (访问密码: 1666)
附录、系统中断向量表及中断函数名
可从AltaRiscv.h中查看