七毛钱 发表于 2022-2-24 10:11

串口体验和不定长数据接收

前言      由于miniUSB的数据线的缺失,串口功能的体验使用外在的串口转USB工具进行。
目标      串口功能的实现。
分析      软件功能的实现的第一步就是要确保硬件连接正确,也就是RX和TX要和工具的串口连接正确,串口实现通信只要RX、TX和地连接上就可以,电不是必须的,逻辑正确就可以传输,软件功能的实现也是对硬件连接的进一步验证。使用的是PA9和PA10对应的UART0,和板载的资源使用的是同一个。
      首先实现串口简单的发数,例如定期发送0x01,以此验证串口配置是否正确和硬件通路是否通畅。      串口配置,包括对应的IO口配置;
[*]//******************************************************************************
[*]//* 函数名称: gd_USART_init
[*]//* 函数描述: 外部中断配置
[*]//* 输入参数:
[*]//* 参数描述: 外部中断初始化配置
[*]//* 输出参数: 无
[*]//* 返回值    : 无
[*]//******************************************************************************
[*]void gd_USART_init(void)
[*]{
[*]/* enable COM GPIO clock */
[*]rcu_periph_clock_enable(RCU_GPIOA);
[*]/* enable USART clock */
[*]rcu_periph_clock_enable(RCU_USART0);
[*]
[*]/* connect port to USART TX */
[*]gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_9);
[*]/* connect port to USART RX */
[*]gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_10);
[*]
[*]/* configure USART TX as alternate function push-pull */
[*]gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_9);
[*]gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, GPIO_PIN_9);
[*]
[*]/* configure USART RX as alternate function push-pull */
[*]gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_10);
[*]gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, GPIO_PIN_10);
[*]
[*]/* USART configure */
[*]usart_deinit(USART0);
[*]usart_word_length_set(USART0, USART_WL_8BIT);
[*]usart_stop_bit_set(USART0, USART_STB_1BIT);
[*]usart_parity_config(USART0, USART_PM_NONE);
[*]usart_baudrate_set(USART0, 115200U);
[*]usart_receive_config(USART0, USART_RECEIVE_ENABLE);
[*]usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);
[*]
[*]/* USART interrupt configuration */
[*]nvic_irq_enable(USART0_IRQn, 0);
[*]/* enable USART TBE interrupt */
[*]//usart_interrupt_enable(USART0, USART_INT_TBE);
[*]usart_enable(USART0);
[*]
[*]//usart_interrupt_flag_clear(USART0,USART_INT_FLAG_IDLE);
[*]//usart_interrupt_enable(USART0, USART_INT_IDLE);
[*]
[*]//USART0_DMA_Configuration();
[*]
[*]}
现象:http://bbs.**/data/attachment/forum/202202/15/215035sdppckvpczvyc52z.png.thumb.jpg

      然后实现printf功能,我们在第一步已经实现了串口的通信,只要再配置printf重定向就可以了,定期发送字符串。
[*]int fputc(int ch, FILE *f)
[*]{
[*]    usart_data_transmit(USART0, (uint8_t) ch);
[*]    while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));
[*]    return ch;
[*]}
现象:http://bbs.**/data/attachment/forum/202202/15/215035fuhgdsadsp7hrdhh.png.thumb.jpg

      在体验了这两种发送方式后就需要来实现串口接收了,printf非常适合调试过程中打印输出调试信息,而在实际的交互过程中是需要使用usart_data_transmit直接进行个性化的发送模式设计。
      串口接收为了实现不定长数据的接收处理,避免多次进入中断,准备采用DMA+串口空闲中断的方式,添加DMA配置,通过收到什么回传什么进行测试。DMA的通道映射参考DMAMUX 映射,可是我并没有找到通道请求表,类如GD32F350的这种:http://bbs.**/data/attachment/forum/202202/15/215035gj8xu6ixihi6l5ss.png.thumb.jpg
      Demo中的串口DMA并没有用到DMAMUX,但是DMAMUX是存在的,中间加了这么一道使DMA的应用更广泛,但是不用时的DMA对应的通道请求时什么样的呢?DMA配置代码:
[*]void USART0_DMA_Configuration(void)
[*]{
[*]dma_parameter_struct dma_init_struct;
[*]/* enable DMA clock */
[*]rcu_periph_clock_enable(RCU_DMA);
[*]
[*]/* initialize DMA channel 1 */
[*]dma_deinit(DMA_CH1);
[*]dma_struct_para_init(&dma_init_struct);
[*]dma_init_struct.request      = DMA_REQUEST_USART0_RX;
[*]dma_init_struct.direction    = DMA_PERIPHERAL_TO_MEMORY;
[*]dma_init_struct.memory_addr= (uint32_t)USART0RecePackBuf;
[*]dma_init_struct.memory_inc   = DMA_MEMORY_INCREASE_ENABLE;
[*]dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
[*]dma_init_struct.number       = DMA_USART0_LEN;
[*]dma_init_struct.periph_addr= (uint32_t)&USART_RDATA(USART0);
[*]dma_init_struct.periph_inc   = DMA_PERIPH_INCREASE_DISABLE;
[*]dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
[*]dma_init_struct.priority   = DMA_PRIORITY_ULTRA_HIGH;
[*]dma_init(DMA_CH1, &dma_init_struct);
[*]
[*]/* configure DMA mode */
[*]dma_circulation_disable(DMA_CH1);
[*]dma_memory_to_memory_disable(DMA_CH1);
[*]/* disable the DMAMUX_MUXCH1 synchronization mode */
[*]dmamux_synchronization_disable(DMAMUX_MUXCH1);
[*]
[*]/* USART DMA enable for reception */
[*]usart_dma_receive_config(USART0, USART_DENR_ENABLE);
[*]
[*]/* enable DMA channel 1 */
[*]dma_channel_enable(DMA_CH1);
[*]dma_flag_clear(DMA_CH1, DMA_FLAG_G);
[*]}

现象:在配置完成后会进入一次空闲中断http://bbs.**/data/attachment/forum/202202/15/215035mt1ftrthrpw8hphw.png.thumb.jpg

      接下来就是简单的通信协议编制了,根据现有的资源只能是控制LED灯的操作了,目前有两种控制模式是通过按键完成的,现在通过通信协议把这两种控制方式写进去。规定一下通信协议的格式:改变展示模式,Data为对应的模式代号:
前导码 (STX)长度命令数据校验和
8A F60x050x900x0EDataCHECKSUM

例如:8A F6 05 90 0e 02 00 A0
控制呼吸灯,Data为对应的开关(0或者1):
前导码 (STX)长度命令数据校验和
8A F60x050x910x0EDataCHECKSUM

例如:8A F6 05 91 0e 01 00 A0
现象如下:http://bbs.**/data/attachment/forum/202202/15/215645kxqxdeabz5qzlbmh.gifhttp://bbs.**/data/attachment/forum/202202/15/215645kdxdz3zqbkkjpw0a.gif

koala889 发表于 2022-4-2 16:35

不定长是如何体现的呢

littlelida 发表于 2022-4-6 12:32

什么情况下,数据是不定长的?
页: [1]
查看完整版本: 串口体验和不定长数据接收