感芯多线程处理器MC3172评估板(四)- 串口的使用

本文介绍感芯MC3172评估板的串口配置与编程方法,包括宏定义、函数封装及程序编写等内容。通过实例演示了如何实现与电脑的串口通信。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

感芯多线程处理器MC3172评估板(一)- 介绍与搭建开发环境 感芯多线程处理器MC3172评估板(二)- 点亮一个LED灯 感芯多线程处理器MC3172评估板(三)- 体验多线程同步并行

目录

前言

一、通用异步收发器(UART)

二、相关宏定义

 三、相关函数封装

四、编写程序

 五、硬件电路

 六、下载程序

 七、实验现象

 八、*注意事项

总结


前言

        上一篇文章通过编程实现两个IO口来感受多线程同步并行运行的效果,这一篇将通过编程串口的相关函数实现与电脑的通信。


一、通用异步收发器(UART)

        MC3172评估板可以配置12个串口,每四个IO一组,在组内串口的输入输出可以任意配置,非常灵活,和FPGA很相似。串口的基本知识不做介绍。

        本次串口选择第0组,选择线程组0,使用了板子上的48M无源晶振,串口波特率设为115200。若设为9600会溢出,115200的刚好,因此,选用115200。

二、相关宏定义

1.INTDEV_SET_CLK_RST(DEV_ADDR,value)

#define INTDEV_SET_CLK_RST(DEV_ADDR,value)      (*(volatile u32*)(DEV_ADDR))=(value)

        这个宏用于对外设进行启动,主要是设置外设使用的时钟频率以及特权组。使能了GPIOx对应的时钟。

        (1)DEV_ADDR是GPCOMx的外设,可以为GPCOM0_BASE_ADDRGPCOM2_BASE_ADDR、GPCOM3_BASE_ADDR、GPCOM4_BASE_ADDR、GPCOM5_BASE_ADDR.等等。

        (2)value参数:一般为(运行|线程组别|外设时钟分频设置)。

2. GPCOM_SET_IN_PORT(GPCOM_SEL,value)

#define GPCOM_SET_IN_PORT(GPCOM_SEL,value)         (*(volatile u32*)(GPCOM_SEL+GPCOM_IN_MODE_ADDR)) = value

        这个宏用于设置 输入管脚(可以在 P0-P3 按需设置)为接收引脚。

        (1)GPIO_SEL是GPCOMx的外设,可以为GPCOM0_BASE_ADDRGPCOM2_BASE_ADDR、GPCOM3_BASE_ADDR、GPCOM4_BASE_ADDR、GPCOM5_BASE_ADDR.等等。

        (2)value:是设置为输入引脚并设置为RXD引脚的引脚,可以为GPCOM_RXD_IS_P0或GPCOM_RXD_IS_P1或GPCOM_RXD_IS_P2或GPCOM_RXD_IS_P3。

3.GPCOM_SET_OUT_PORT(GPCOM_SEL,value)

#define GPCOM_SET_OUT_PORT(GPCOM_SEL,value)                 (*(volatile u32*)(GPCOM_SEL+GPCOM_OUT_MODE_ADDR)) = value

这个宏用于设置 输出管脚为发送引脚。

4.GPCOM_SET_COM_MODE(GPCOM_SEL,value)

#define GPCOM_SET_COM_MODE(GPCOM_SEL,value)                 (*(volatile u32*)(GPCOM_SEL+GPCOM_ITEM1_ADDR)) = value

 这个宏用于设置工作模式。

5.GPCOM_SET_COM_SPEED(GPCOM_SEL,clk_speed,baudrate)

#define GPCOM_SET_COM_SPEED(GPCOM_SEL,clk_speed,baudrate)   (*(volatile u32*)(GPCOM_SEL+GPCOM_ITEM2_ADDR)) = (((clk_speed/baudrate)-1)<<8)+(clk_speed/baudrate)/2-2

  这个宏用于设置串口工作频率和波特率,参数分别为GPCOM,外设时钟,串口波特率。

6.GPCOM_SET_OVERRIDE_GPIO(GPCOM_SEL,value) 

#define GPCOM_SET_OVERRIDE_GPIO(GPCOM_SEL,value)            (*(volatile u32*)(GPCOM_SEL+GPCOM_OVERRIDE_GPIO_ADDR)) = value

  这个宏用于设置串口管脚映射 GPIO。

7.GPCOM_GET_RX_WP(GPCOM_SEL)

#define GPCOM_GET_RX_WP(GPCOM_SEL)                          (*(volatile u8*)(GPCOM_SEL+GPCOM_RX_DATA_WP_ADDR))

  这个宏用于读取当前 RX 的缓存 FIFO 写指针。

8.GPCOM_GET_RX_DATA(GPCOM_SEL,rp) 

#define GPCOM_GET_RX_DATA(GPCOM_SEL,rp)                     (*(volatile u32*)(GPCOM_SEL+GPCOM_RX_DATA_BUF0_ADDR+(((rp&0x7)*8))))

  这个宏用于读取当前 RX 的缓存 FIFO 读指针 rp 指向的数据。

9.GPCOM_TX_FIFO_FULL(GPCOM_SEL)

#define GPCOM_TX_FIFO_FULL(GPCOM_SEL)            (((*(volatile u8*)(GPCOM_SEL+GPCOM_TX_DATA_RP_ADDR))^0x8)==(*(volatile u8*)(GPCOM_SEL+GPCOM_TX_DATA_WP_ADDR)))

  这个宏用于检查 TX 的发射缓存是否已满。

10.GPCOM_TX_FIFO_EMPTY(GPCOM_SEL)

#define GPCOM_TX_FIFO_EMPTY(GPCOM_SEL)           (((*(volatile u8*)(GPCOM_SEL+GPCOM_TX_DATA_RP_ADDR)))    ==(*(volatile u8*)(GPCOM_SEL+GPCOM_TX_DATA_WP_ADDR)))

  这个宏用于检查 TX 的发射缓存是否已空。

11.GPCOM_PUSH_TX_DATA(GPCOM_SEL,value)

#define GPCOM_PUSH_TX_DATA(GPCOM_SEL,value)                 (*(volatile u32*)(GPCOM_SEL+GPCOM_TX_DATA_BUF0_WPINC_ADDR+ (( (*(volatile u32*)(GPCOM_SEL+GPCOM_TX_DATA_WP_ADDR))*8 )&0x3f) )) = value

  这个宏用于把 value 送入 TX 发射缓存(TX 的发射缓存一共有 8 层,可以一次性送 8 个字节,非常高效)。

 三、相关函数封装

1.串口初始化函数

         MC3172评估板可以配置12个串口,为了方便初始化各个串口,将函数封装成如下。可通过修改函数的gpcom_sel参数来初始化相应的串口,该函数已默认将每组初始化串口的P2为RXD引脚,P3为TXD引脚。Thread_group为线程组,rate为串口波特率。

/*初始化UART0*/
void Uart_Init(u32 Thread_group,u32 gpcom_sel,u32 rate)
{
    /*启动外设*/
    //这个宏用于对外设进行启动共 12 个可选,具体位置见 MC3172 芯片手册,INTDEV_CLK_IS_CORECLK_DIV4:系统时钟分频
    INTDEV_SET_CLK_RST(gpcom_sel,(INTDEV_RUN|Thread_group|INTDEV_CLK_IS_CORECLK_DIV4));
    /*设置RXD引脚*/
    //这个宏用于设置 P2 为输入管脚(可以在 P0-P3 按需设置)P2为接收引脚
    GPCOM_SET_IN_PORT(gpcom_sel,(GPCOM_RXD_IS_P2));
    /*设置TXD引脚*/
    //这个宏用于设置 P3 为输出管脚(可以在 P0-P3 按需设置,P3为发送引脚
    GPCOM_SET_OUT_PORT(gpcom_sel,(\
            GPCOM_P0_OUTPUT_DISABLE|GPCOM_P1_OUTPUT_DISABLE|GPCOM_P2_OUTPUT_DISABLE|GPCOM_P3_OUTPUT_ENABLE|\
            GPCOM_P1_IS_HIGH       |GPCOM_P1_IS_HIGH       |GPCOM_P1_IS_HIGH       |GPCOM_P3_IS_TXD\
            ));
    /*设置工作模式*/
    GPCOM_SET_COM_MODE(gpcom_sel,GPCOM_UART_MODE);
    /*设置串口工作频率和波特率*/  
    GPCOM_SET_COM_SPEED(gpcom_sel,12000000,rate);//参数分别为GPCOM,外设时钟,串口波特率,
    /*映射引脚*/
    GPCOM_SET_OVERRIDE_GPIO(gpcom_sel,(\
            GPCOM_P2_OVERRIDE_GPIO|GPCOM_P2_INPUT_ENABLE|\
            GPCOM_P3_OVERRIDE_GPIO\
            ));
}

2.发送单个字节函数

/*发送单个byte*/
void Send_Byte(u32 gpcom_sel,u8 dat)
{
    while(GPCOM_TX_FIFO_FULL(gpcom_sel));//等待发送结束
    GPCOM_PUSH_TX_DATA(gpcom_sel,dat);//发送数据dat
}

 3.发送多个字节函数

/*发送多个字节*/
void Send_MultiByte(u32 gpcom_sel,u8 *dat)
{
    while(*dat!='\0')//判断是否结束
    {
        Send_Byte(gpcom_sel, *dat++);//发送字节
    }
}

4.接收处理函数

         接收到的数据储存在USART_RX_BUF里,可在行编写相关的处理内容。整体代码如下:

////接收处理函数
void Rx_Data(u32 gpcom_sel)
{
    u8 rx_data_rp=0;
    u8 Res=0;
    rx_data_rp=GPCOM_GET_RX_WP(gpcom_sel);//读取当前 RX 的缓存 FIFO 写指针
    while(1) {
         if(rx_data_rp!=(GPCOM_GET_RX_WP(gpcom_sel))){
             Res=GPCOM_GET_RX_DATA(gpcom_sel,rx_data_rp);//读取当前 RX 的缓存 FIFO 读指针 rx_data_rp 指向的数据。
             if((USART_RX_STA&0x8000)==0)//接收未完成
              {
                  if(USART_RX_STA&0x4000)//接收到了0x0d
                  {
                      if(Res!=0x0a)USART_RX_STA=0;//接收状态标记
                      else //接收完成了
                      {
                        //添加串口接收到数据处理的内容
                        /*代码添加处*/
                        USART_RX_STA=0;//接收状态标记清零
                        memset(USART_RX_BUF,'\0',200);//清除缓存空间
                        rx_data_rp=GPCOM_GET_RX_WP(gpcom_sel);//读取当前 RX 的缓存 FIFO 写指针
                      }
                  }
                  else {//还没收到0X0D
                      if(Res==0x0d)USART_RX_STA|=0x4000;
                      else {
                          USART_RX_BUF[USART_RX_STA]=Res ;
                          USART_RX_STA++;
                          if(USART_RX_STA>(UART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收
                    }
                    rx_data_rp++;
                    rx_data_rp&=0x0f;
                }
              }
         }
    }
}

四、编写程序

       (1) 在main.c文件中的void thread0_main(void)里编写代码程序如下:

void thread0_main(void)
{
    Uart_Init(INTDEV_IS_GROUP0,G_COM0,115200);
    Send_Byte(G_COM0,'H');
    Send_MultiByte(G_COM0,"ok\r\n");
    while(1){

    }
    thread_end();
}

     (2) 在Rx_Data()函数里添加代码如下,实现当接收数据第一个字符为A时,MC3172向电脑发送"Test2 A is ok\r\n",等等功能。

Send_MultiByte(gpcom_sel,USART_RX_BUF);
Send_MultiByte(gpcom_sel,"\r\n");
if(USART_RX_BUF[0]=='A')
{
    Send_MultiByte(gpcom_sel,"Test2 A is ok\r\n");
}
if(USART_RX_BUF[0]=='B')
    Send_MultiByte(gpcom_sel,"Test B is ok\r\n");
if(USART_RX_BUF[0]=='B'&&USART_RX_BUF[1]=='C')
    Send_MultiByte(gpcom_sel,"Test BC is ok\r\n");

      (3) 在main.c文件中的void thread4_main(void)里接收函数如下:

void thread4_main(void)
{
    while(1){
        Rx_Data(G_COM0);
    }
    thread_end();
}

 五、硬件电路

1.MC3172引脚图

参考《感芯MC3172手册_V1.03》里的 表 2-1 MC3172 LQFP100 引脚定义和IO排列顺序图

表 2-1 MC3172 LQFP100 引脚定义
IO排列顺序图

         同时也非常感谢一个网友的分享,将引脚定义的功能标准在IO排列顺序图里如下图,方便我们查看。

2. 引脚与USB转TTL模块的连接方式

        由上面的函数和手册可知,本次项目使用的COM0,PA2为RXD引脚,PA3为TXD引脚,因此将PA2接模块上的TXD引脚,PA3接RXD引脚。

 六、下载程序

        将MC3172评估板通过USB口接到电脑,然后打开Release文件夹下的开发板程序下载_v1.1.exe,这时就会识别出GX_LINK#0设备(也有可能是其它名字),点击连接设备,接着选择生成的*.hex固件,再点击烧录固件,最后等到进度条走到100%则下载成功。

 七、实验现象

        打开电脑串口调试助手,将其右侧的参数设置和代码中的一致,并打开串口。程序下载成功后,在串口显示区会输出“Hok”。点击多条发送窗口并输入相关的内容后,分别点击发送,对应串口显示区会显示评估板发送来的信息如下。

 八、*注意事项

        本次项目的波特率要根据实际计算,太低会超出,太高会不足,尽量满足100<(外设时钟/波特率)<200。我使用的是板子上的无源晶振48M,根据公式“外设时钟=系统时钟(48M)/时钟分频” 可计算出该外设的实际时钟频率为12000000。使用波特率为9600时超出,115200的不会,所以选择了115200。


总结

        以上就是对MC3172评估板串口学习过程记录分享,由于环境条件,本次项目只测试了一个串口,有条件的伙伴可以测试运行和体验一下多个串口的使用。如果文章中有误,有不足之处请大家多多关照并指出,谢谢!

<think>好的,我现在需要帮助用户解决ML307R核心串口调试和配置问题。首先,我需要了解用户的具体需求,他们可能遇到了串口通信不成功、配置参数错误或者硬件连接问题。接下来,我应该整理出调试的基本步骤,包括硬件连接、软件配置、常见问题排查等。首先,硬件连接方面,用户需要确认核心串口引脚是否正确连接到调试工具,比如USB转TTL模块。需要提醒用户检查TX、RX是否交叉连接,电源是否稳定,接地是否正确。同时,注意电压匹配,避免损坏设备。然后是软件配置部分,用户可能需要使用串口调试助手,如Putty、SecureCRT或者Arduino的串口监视器。需要指导用户正确设置波特率、数据位、停止位和校验位。ML307R常见的波特率可能是115200,但具体要看文档。如果用户没有文档,可能需要建议他们尝试常用波特率或者联系供应商获取准确参数。接着是常见问题,比如无法接收或发送数据。这时候需要分步骤排查:检查硬件连接是否正确,确认线缆是否完好;软件参数是否匹配;是否有固件问题,可能需要重新烧录固件或检查配置脚本。此外,还要考虑是否有干扰或者电源不稳定导致通信失败。另外,根据用户提到的MC3172微控制器的引用,虽然和ML307R不一定直接相关,但可以借鉴其中的多线程处理思路。比如,如果ML307R支持多任务处理,可能在串口中断处理上有类似的高效机制,确保实时响应。不过这部分需要结合具体片资料,不能假设。用户可能需要具体的配置教程,比如如何通过AT指令配置串口参数,或者如何通过编程设置UART寄存器。如果核心使用特定的开发环境,比如基于Keil或IAR,可能需要指导如何编写初始化代码。此外,日志记录和调试信息输出也是关键,帮助用户定位问题。还要考虑到用户可能的操作失误,比如串口线接反、波特率设置错误,或者是驱动未安装。需要提醒他们逐步检查每个环节,使用已知良好的设备进行交叉测试。最后,整理出常见问题列表,如无法识别串口设备、数据乱码、通信中断等,并提供相应的解决方法。确保回答结构清晰,步骤详细,用户能够按部就班地进行调试。</think>### ML307R核心串口调试与配置方法 #### 一、硬件连接步骤 1. **确认串口引脚**:查找ML307R核心的UART引脚(通常标注为TX、RX、GND),例如: - TXD: 数据发送引脚 - RXD: 数据接收引脚 - GND: 接地引脚 2. **连接USB转TTL模块**: - 核心TXD → 转接模块RXD - 核心RXD → 转接模块TXD - 确保GND共地连接 3. **供电检查**:核心需通过外部电源或USB稳定供电(电压范围参考手册,常见3.3V或5V)[^1] #### 二、软件配置流程 1. **串口调试工具设置**(以SecureCRT为例): - 选择正确COM端口(设备管理器中查看) - 波特率:通常为115200(具体以手册为准) - 数据位:8位 - 停止位:1位 - 校验位:无 ```python # 示例:Python串口通信初始化代码 import serial ser = serial.Serial('COM3', baudrate=115200, timeout=1) ser.write(b'AT\r\n') # 发送测试指令 response = ser.readline() print(response.decode()) ``` 2. **AT指令配置**(若支持): - 常用指令: - `AT+UART=115200,8,1,0` 设置串口参数 - `AT+TEST` 测试通信状态 - 需根据具体模组文档调整指令格式 #### 三、常见问题排查 | 问题现象 | 解决方法 | |---------|----------| | 无数据接收 | 1. 检查TX/RX是否反接<br>2. 测量引脚电压是否正常(高电平>2.5V)<br>3. 更换USB转TTL模块测试 | | 数据乱码 | 1. 确认波特率/校验位与设备一致<br>2. 检查电源纹波(示波器测量)<br>3. 降低通信速率测试 | | 间歇性断连 | 1. 检查焊接是否虚焊<br>2. 缩短线缆长度(建议<30cm)<br>3. 添加10kΩ上拉电阻 | #### 、高级调试技巧 1. **逻辑分析仪抓包**:使用Saleae/PulseView捕获实际波形,分析时序偏差 2. **中断优先级配置**:若使用MC3172多线程控制器,可为串口中断分配独立线程实现零延迟响应[^1] 3. **DMA传输优化**:通过直接内存访问减少CPU占用(需查阅片手册确认支持性)
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值