打印

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

[复制链接]
822|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
七毛钱|  楼主 | 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();
  • }

现象:



        然后实现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;
  • }

现象:



        在体验了这两种发送方式后就需要来实现串口接收了,printf非常适合调试过程中打印输出调试信息,而在实际的交互过程中是需要使用usart_data_transmit直接进行个性化的发送模式设计。


        串口接收为了实现不定长数据的接收处理,避免多次进入中断,准备采用DMA+串口空闲中断的方式,添加DMA配置,通过收到什么回传什么进行测试。DMA的通道映射参考DMAMUX 映射,可是我并没有找到通道请求表,类如GD32F350的这种:


        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);
  • }

现象:在配置完成后会进入一次空闲中断



        接下来就是简单的通信协议编制了,根据现有的资源只能是控制LED灯的操作了,目前有两种控制模式是通过按键完成的,现在通过通信协议把这两种控制方式写进去。

规定一下通信协议的格式:

改变展示模式,Data为对应的模式代号:

前导码 (STX)

长度

命令

数据

校验和

8A F6

0x05

0x90

0x0E

Data

CHECKSUM


例如:8A F6 05 90 0e 02 00 A0


控制呼吸灯,Data为对应的开关(0或者1):

前导码 (STX)

长度

命令

数据

校验和

8A F6

0x05

0x91

0x0E

Data

CHECKSUM


例如:8A F6 05 91 0e 01 00 A0


现象如下:


使用特权

评论回复
沙发
koala889| | 2022-4-2 16:35 | 只看该作者
不定长是如何体现的呢

使用特权

评论回复
板凳
littlelida| | 2022-4-6 12:32 | 只看该作者
什么情况下,数据是不定长的?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

342

主题

2358

帖子

4

粉丝