前言 刚收到中科微CSM32RV20 开发板的时候开发环境搭建,点灯都很顺利,因为比较忙就没急着做项目,最近发现例程中的串口,除了uart1外,其他几个在中断方式下都不好用。经过排查发现uart.c只是实现了uart1的功能,其他的几个串口代码是不完整的。
一、新建一个多串口的项目 打开CSMStudio编程环境,新建一个项目:My_uart_1,如下图:
将uart1,uart2,uart3,uart4都设置成中断模式,并开启单个中断和总中断。
- UART_Init_IT_case1(UART1);//中断模式
- UART_Init_IT_case1(UART2);//中断模式
- UART_Init_IT_case1(UART3);//中断模式
- UART_Init_IT_case1(UART4);//中断模式
- Interrupt_Enable(UART1_int_ID);//CLIC使能单个中断
- Interrupt_Enable(UART2_int_ID);//CLIC使能单个中断
- Interrupt_Enable(UART3_int_ID);//CLIC使能单个中断
- Interrupt_Enable(UART4_int_ID);//CLIC使能单个中断
-
- SYS_Interrupt_Enable();//CLIC开总中断
复制代码
在main()的循环中增加发送代码:
- while(1)
- {
-
- UART1_putbuf("test1----n");
- UART2_putbuf("test2----n");
- UART3_putbuf("test3----n");
- UART4_putbuf("test4----n");
- Delay32M_ms(1000);
- }
复制代码
间隔1s每个串口发送一帧数据。 将USB-TTL线分别连接开发板的:UART1:PA5,PA6,UART2:PA3,PA4,UART3:PA10,PA11,UART4:PA14,PA15,通过串口调试程序就可以收到开发板的数据。
二、 uart.c文件的完善 2.1 putbuf函数定义 新建项目之后,如果用原来的uart.c文件,如果我们设置uart2,uart3为中断模式,编译的时候就会报错。而且启用中断模式数据回环测试时,会发现串口实际是一个一个字符发送的。打开uart.c可以看到实际上,void UART1_putbuf(uint8_t ubyte)发送的是单个的字符。
- void UART1_putbuf(uint8_t ubyte)//数据放入缓存,适用于中断模式
- {
- Interrupt_Disable(UART1_int_ID);//CLIC关闭单个中断
- //_REG8(CLIC_INtiE_BASE,UART1_int_ID) = 0;//关闭串口中断
-
- if(U1_outstart + ULEN != U1_outend )
- {
- U1_outbuf[U1_outend++&(ULEN-1)] = ubyte;
- //upack[unum++] = ubyte;
- }
-
- if((U1_outactive==0)&&((UART1->CTRL&0x00800000) == 0))
- {
- UART1->DATA = U1_outbuf[U1_outstart++&(ULEN-1)];
- U1_outactive = 1;
- }
-
- Interrupt_Enable(UART1_int_ID);//CLIC使能单个中断
- //_REG8(CLIC_INTIE_BASE,UART1_int_ID) = 1;//开启串口中断
-
- }
复制代码
同时,我们注意到uart.h中的 void UART1_putchar(uint8_t ubyte);//数据放入缓存,适用于中断模式, 应该是更为恰当的定义。
- #ifndef UART_H_
- #define UART_H_
-
- #include "stdio.h"
-
- #define ULEN 32
-
- void UART_Init_case1(UART_TypeDef *UARTx); //非中断模式
- void UART_Init_IT_case1(UART_TypeDef *UARTx); //中断模式
-
- void Uart_Send(UART_TypeDef *UARTx,uint8_t *packet,uint16_t lenth);//适用于非中断发送模式
- void Uart_Reveive(UART_TypeDef *UARTx,uint8_t *packet,uint16_t lenth);//适用于非中断发送模式
-
- void UART1_putchar(uint8_t ubyte);//数据放入缓存,适用于中断模式
- uint8_t UART1_getchar(void);//取数据缓存
-
- void UART1_IRQhandler(void) __attribute__((interrupt("SiFive-CLIC-preemptible")));
- void UART2_IRQhandler(void) __attribute__((interrupt("SiFive-CLIC-preemptible")));
- void UART3_IRQhandler(void) __attribute__((interrupt("SiFive-CLIC-preemptible")));
- void UART4_IRQhandler(void) __attribute__((interrupt("SiFive-CLIC-preemptible")));
-
- ssize_t _write(int file,const void *ptr, size_t len);
-
-
- #endif
复制代码
重新定义putbuf和putchar函数如下:
- void UART1_putbuf(uint8_t ubyte)//数据放入缓存,适用于中断模式
- {
- Interrupt_Disable(UART1_int_ID);//CLIC关闭单个中断
- //_REG8(CLIC_INTIE_BASE,UART1_int_ID) = 0;//关闭串口中断
-
- if(U1_outstart + ULEN != U1_outend )
- {
- U1_outbuf[U1_outend++&(ULEN-1)] = ubyte;
- //upack[unum++] = ubyte;
- }
-
- if((U1_outactive==0)&&((UART1->CTRL&0x00800000) == 0))
- {
- UART1->DATA = U1_outbuf[U1_outstart++&(ULEN-1)];
- U1_outactive = 1;
- }
-
- Interrupt_Enable(UART1_int_ID);//CLIC使能单个中断
- //_REG8(CLIC_INTIE_BASE,UART1_int_ID) = 1;//开启串口中断
-
- }
- void UART1_putchar(uint8_t ubyte)//数据放入缓存,适用于中断模式
- {
- Interrupt_Disable(UART1_int_ID);//CLIC关闭单个中断
- //_REG8(CLIC_INTIE_BASE,UART1_int_ID) = 0;//关闭串口中断
-
- if(U1_outstart + ULEN != U1_outend )
- {
- U1_outbuf[U1_outend++&(ULEN-1)] = ubyte;
- //upack[unum++] = ubyte;
- }
-
- if((U1_outactive==0)&&((UART1->CTRL&0x00800000) == 0))
- {
- UART1->DATA = U1_outbuf[U1_outstart++&(ULEN-1)];
- U1_outactive = 1;
- }
-
- Interrupt_Enable(UART1_int_ID);//CLIC使能单个中断
- //_REG8(CLIC_INTIE_BASE,UART1_int_ID) = 1;//开启串口中断
-
- }
复制代码
2.2 其他串口的发送函数 Uart.c中只定义了UART1口的中断收发函数,UART2,UART3,UART4口的函数是缺失的。参照UART1的函数,编写其他串口的中断收发函数。 2.3 中断服务函数完善 对比void UART1_IRQhandler(void)和void UART2_IRQhandler(void)会发现,UART2,UART3,UART4的中断服务函数是缺失的,参考UART1补全其他的服务函数。
|