感芯多线程处理器MC3172评估板(一)- 介绍与搭建开发环境 感芯多线程处理器MC3172评估板(二)- 点亮一个LED灯 感芯多线程处理器MC3172评估板(三)- 体验多线程同步并行
目录
前言
上一篇文章通过编程实现两个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_ADDR、GPCOM2_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_ADDR、GPCOM2_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排列顺序图
![](https://i-blog.csdnimg.cn/blog_migrate/04f9e11259fe37261f22d1bd6c70206b.png)
![](https://i-blog.csdnimg.cn/blog_migrate/35c75d12bb42babcc3b09c098b74580a.png)
同时也非常感谢一个网友的分享,将引脚定义的功能标准在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评估板串口学习过程记录分享,由于环境条件,本次项目只测试了一个串口,有条件的伙伴可以测试运行和体验一下多个串口的使用。如果文章中有误,有不足之处请大家多多关照并指出,谢谢!