首页 > 其他分享 >【WCH蓝牙系列芯片】-基于CH582开发板—利用定时器加DMA方式模拟串口输出

【WCH蓝牙系列芯片】-基于CH582开发板—利用定时器加DMA方式模拟串口输出

时间:2024-10-10 11:02:47浏览次数:1  
标签:DMA 定时器 dma timer 开发板 TMR2 串口 buf

------------------------------------------------------------------------------------------------------------------------------------

  在使用CH582芯片开发测试中,有个实际的用途是利用串口输出日志的方式,来进行程序的调试。CH582芯片一共提供了 4 组全双工的异步串口 UART0/1/2/3;但是如果在应用中四个串口都用完了,没有单独空的串口作为日志输出,此时,可以利用芯片的定时器加DMA方式模拟串口输出的方式解决这一问题。

  在CH582芯片上,只有TMR1和TMR2支持DMA功能,所以使用PA11所在的定时器2引脚作为模拟串口的输出脚。

  先初始化定时器和DMA,配置PA11为推挽输出模式,设置主频和波特率参数

static uint32_t timer_dma_buf[11];   //存储DMA(直接内存访问)传输的数据
static uint32_t bit_cnt;   //用于存储每个位的计数值

//接收主频(sys_frq)和波特率(baudrate)
void ch5xx_timer_uart_init(uint32_t sys_frq,uint32_t baudrate)  //初始化UART接口的函数
{
    bit_cnt = sys_frq/baudrate;   //计算每个位的计数值
    timer_dma_buf[0] = bit_cnt;   //将计算出的位计数值存储在DMA缓冲区的第一个元素中
    timer_dma_buf[9] = 0;   //将DMA缓冲区的第十个元素设置为0
    timer_dma_buf[10] = 0;   //将DMA缓冲区的第十一个元素设置为0
    timer_dma_buf[11] = 0;  //将DMA缓冲区的第十二个元素设置为0
    GPIOA_SetBits(GPIO_Pin_11);
    GPIOA_ModeCfg(GPIO_Pin_11, GPIO_ModeOut_PP_5mA);   //推挽输出
#if 0
//LED闪烁
    uint32_t i=100;
    while(i--)
    {
      GPIOB_InverseBits(GPIO_Pin_22);
      DelayMs(1);
    }
    GPIOB_ResetBits(GPIO_Pin_22);
    DelayMs(10);
    GPIOB_SetBits(GPIO_Pin_22);
#endif

    TMR2_PWMInit(Low_Level, PWM_Times_1);  //初始化定时器2为PWM(脉冲宽度调制)模式
    TMR2_PWMCycleCfg(bit_cnt);    //配置PWM周期为bit_cnt
    TMR2_Disable();  //禁用定时器2

    TMR2_PWMActDataWidth(0); // 占空比 50%, 修改占空比必须暂时关闭定时器
    TMR2_PWMEnable();  //启用PWM
    TMR2_Enable();   //启用定时器2
    TMR2_ITCfg(ENABLE, RB_TMR_IE_DMA_END);  //启用定时器2的DMA结束中断

    R32_TMR2_DMA_BEG = (uint32_t)&timer_dma_buf[0];   //设置DMA传输的起始地址为timer_dma_buf数组的开始
    R32_TMR2_DMA_END = (uint32_t)&timer_dma_buf[10];   //设置DMA传输的结束地址为timer_dma_buf数组的第十个元素
    ch5xx_timer_printf("ch5xx_timer uart init done\r\n");  //调用ch5xx_timer_printf函数打印初始化完成的消息
}

 

 

//用于通过定时器发送一系列字节数据
//uint8_t *data:指向要发送数据的指针
//uint32_t len:要发送的数据长度
__HIGH_CODE
void ch5xx_timer_send(uint8_t *data,uint32_t len)
{
    while(len)
    {
      ch5xx_timer_send_byte(*data);  //传入当前指向的数据字节
      data ++;
      len --;
    }
}



//通过定时器和DMA(直接内存访问)发送单个字节的数据。将一个字节的数据位逐个发送出去
__HIGH_CODE
void ch5xx_timer_send_byte(uint8_t byte)
{
  uint32_t shift_data = byte;  //用于存储要发送的字节数据
  uint32_t *p = &timer_dma_buf[1];  //定义一个指向timer_dma_buf数组第二个元素的指针p。timer_dma_buf是一个预先定义的数组,用于存储DMA传输的数据

  //一个字节有8位
  for(uint8_t j=0;j<8;j++)
  {
      if(shift_data & 0x01u)  //检查shift_data的最低位是否为1,通过与操作0x01u(即二进制的00000001)
      {
          *p = 0;  //如果最低位为1,则将指针p指向的数组元素设置为0,表示在UART信号中发送一个逻辑高电平
      }
      else
      {
          *p = bit_cnt; // 将指针p指向的数组元素设置为bit_cnt,用于存储定时器的计数值,表示在UART信号中发送一个逻辑低电平。
      }
      shift_data >>=1;  //将shift_data右移一位,这样下一次循环将检查下一个位
      p++;  //指针p向前移动
  }

  R32_TMR2_DMA_BEG = (uint32_t)&timer_dma_buf[0]; // 设置DMA传输的起始地址为timer_dma_buf数组的开始
  TMR2_ClearITFlag(RB_TMR_IE_DMA_END);  //清除定时器2的DMA结束中断标志
  R8_TMR2_CTRL_DMA = RB_TMR_DMA_ENABLE;  //启用定时器2的DMA

  //wait dma end   等待DMA传输结束
  while(!TMR2_GetITFlag(RB_TMR_IF_DMA_END));  //使用一个while循环来轮询DMA结束中断标志,直到它被设置,表示DMA传输已经完成
  R8_TMR2_CTRL_DMA = 0;   //禁用定时器2的DMA
}



//将格式化的字符串发送到一个串行接口
void ch5xx_timer_printf(char *fmt,...)
{
    char buffer[128];   //一个字符数组buffer,大小为128字节,用于存储格式化后的字符串
    unsigned char i=0;
    va_list arg_ptr;    // 定义了一个变量参数列表arg_ptr
    va_start(arg_ptr,fmt);  //初始化变量参数列表arg_ptr
    uint32_t len = vsnprintf(buffer,128,fmt,arg_ptr);  // 调用vsnprintf函数将格式化的字符串写入buffer
    va_end(arg_ptr);  //结束对变量参数列表arg_ptr的使用
    ch5xx_timer_send(buffer,len);  //调用ch5xx_timer_send函数发送buffer中的数据,发送的长度由len指定
}

 

在主函数中,只要调试初始化函数,传入对应的主频和波特率参数,这里设置主频时60M,波特率在115200,再调用ch5xx_timer_printf函数直接就可以输出日志。2M波特率测试也是可以。

通过串口助手设置好对应的波特率,可以看到正确打印的数据参数。

 

标签:DMA,定时器,dma,timer,开发板,TMR2,串口,buf
From: https://www.cnblogs.com/ZYL-FS/p/18455891

相关文章

  • 3DMAX云渲染:工业设计领域的新突破!
    随着数字化时代的到来,工业设计领域正经历着一场革命性的变革。3DMAX云渲染技术以其卓越的性能和灵活性,成为推动这一变革的关键力量。本文将探讨3DMAX云渲染技术如何为工业设计带来新突破,并分析其在工业设计领域的应用前景。一、3DMAX云渲染技术概述3DMAX云渲染技术是一种将渲染......
  • 串口的“窗口”应用(如何通过串口打印其他寄存器内的数据)
    一、串口应用概述本文重点叙述使用串口打印其他寄存器内的数据,并且使用STM32的HAL库进行代码编写。对于串口这个外设,我们一开始接触的就是(串口与上位机通信)用串口返回我们发送的数据。这个实验,可以让我们对串口有一个较为直观的感受。在这个实验中,串口打印的数据来自串口自......
  • 九、5 USART串口数据包
    数据包作用:把一个个单独的数据给打包起来,将同一批的数据进行打包和分割,方便接收方进行识别,方便我们进行多字节的数据通信。1、串口收发HEX数据包(1)数据包的格式是个人规定的,如以FF为包头,FE为包尾,用于控制接收防止数据与包头包尾重复的处理方法:1)限制载荷数据的范围:可以在发......
  • 串口使用DMA数据接收和发送
    串口DMA部分在这里我一共分3个部分进行介绍,第一部分介绍什么是DMA第二部分是介绍串口DMA+空闲中断实现不定长数据的收发。第三部分是串口DMA中断实现数据收发。第一部分DMA介绍一、基本概念DMA是直接寄存器,这是指一种高速的数据传输操作,允许在外部设备和存储器和寄存器......
  • ESP8266 开发板网络时钟和天气 OLED 显示
    ESP8266开发板网络时钟和天气OLED显示开发板详见:物联网开发板-ESP8266-立创开源硬件平台(oshwhub.com)网络时钟OELD显示代码#include<Arduino.h>#include<U8g2lib.h>#include<time.h>#include<SPI.h>#include<Wire.h>#include<NTPClient.h>//changene......
  • DMA数据转运
    一.DMA数据转运基本信息DMA直接寄存器数据转运就是将数据在外设与寄存器,寄存器与寄存器之间来回转运有12个独立可配置通道:DMA1(7个)DMA2(5个).数据转运可以是外设寄存器到存储器,或者存储器内部的Flash到SRAM以及SRAM到SRAM.因为Flash是只读的所以不能进行SRAM到Flash,或者......
  • Linux查看触摸坐标点的方法,触觉智能RK3562开发板,瑞芯微、全志等通用
    平时遇到键盘、鼠标、触摸板等输入设备无响应等异常情况时,一般通过更换设备判断异常。但在遇到更换正常设备后,输入仍然异常的情况下,可以借助evtest工具查看内核的上报事件信息,协助定位问题所在。本次使用的是触觉智能EVB3562开发板进行演示,搭载瑞芯微RK3562/RK3562J芯片,该方法也......
  • 【花雕学编程】Arduino动手做(232)---ESP32-S3 CAM使用模拟量霍尔检测磁场并设定阈值控
    37款传感器与执行器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里准备逐一动手尝试系列实验,不管成功(程序走通)与否,都会记录下来——小小的......
  • 教你如何免费获取股票数据用python、JavaScript (Node.js)、JAVA等多种语言的实例代码
    ​近一两年来,股票量化分析逐渐受到广泛关注。而作为这一领域的初学者,首先需要面对的挑战就是如何获取全面且准确的股票数据。因为无论是实时交易数据、历史交易记录、财务数据还是基本面信息,这些数据都是我们进行量化分析时不可或缺的宝贵资源。我们的核心任务是从这些数据......
  • N32L40x基于串口的IAP升级升级速度2Mbps+上位机工具
    1.软件升级流程mcu开机上位机发送0xaa,0xaa,0x55,0x55,通知mcu进入升级状态,在收到该指令后,mcu擦除旧的APP程序,发送进入升级状态的指令,通知上位机进入升级状态擦除完成后进入升级状态,等待上位机发送升级包上位机开始发送数据包mcu接收数据包,并等待一个完成的数据包,每个......