【STC库函数】UART异步串口通信的使用

发布于:2024-12-21 ⋅ 阅读:(11) ⋅ 点赞:(0)

今天来看看UART的使用。

串口是嵌入式领域最常用的通讯方式之一了。

STC32G12K128有俩异步串口,串口三和串口四。

STC8G1K08A是只有一个串口,虽然表格没写是哪个,但是我查了一下,是串口一。

关于串口大家应该都比较熟悉了,所以我们直接讲如何使用STC库函数来使用串口。

以下都是以STC32为例,STC8需要自行去对应手册查,不过流程大差不差。

我们一般就使用8位数据位,1位停止位,无校验位。

STC的UART有两种工作模式。

因为我们使用8位数据位,所以一般采用模式0。

剩下我们要确定的就是波特率了。

有俩定时器可以用,不过我们优先使用定时器3,因为串口2(同步串口)只能使用定时器2,为了避免冲突,我们使用定时器3,不过如果你确定用不到串口2的话使用定时器2也是可以的。

波特率计算公式就如同上表,虽然不复杂,但我也懒得计算,好在我们使用库函数的话不用我们自己去算。

我们需要把STC32G_UART.cSTC32G_UART_Isr.c两个文件加入到我们的工程里。

接着使用下面这个函数UART_Configuration来配置串口。

参数一指定串口,参数二是结构体变量的指针,用来进行具体配置。

从上往下依次是:

串口模式,刚刚有提了,我们就用模式0,可变波特率8位数据位,UART_8bit_BRTx

波特率发生器,也就是指定使用的时钟,我们使用定时器3,BRT_Timer3,我这边假设使用的是串口3,不过如果我们使用的是串口4,那么我们就只能用定时器4。或者使用定时器2,这是所有串口都能用的,不过不使用的理由刚刚也说了,串口2只能用定时器2,只有在确定用不到串口2的时候我们才能用定时器2。

波特率,我们直接填写数值就行,范围是110 ~ 115200,可以超过范围,但是没必要。

是否多机通讯,一般不用,我们选择DISABLE

是否接收,如果要接收的话选择ENABLE,如果只需要串口发送数据,那么可以DISABLE

是否波特率加倍,这个直接DISABLE,用不着,并且只有串口1能用。

配置完之后有俩函数可以发送数据,分别是发送字节和发送字符串的。

懂了发送,那我们还需要懂的接收。

关于接收,我们直接搬官方的的示例代码即可,因为在串口的中断函数里已经帮我们把收到的数据收好了,我们只需要学着示例代码把东西取出来即可。

	while (1)
	{
		delay_ms(1);
		if(COM3.RX_TimeOut > 0)		//超时计数
		{
			if(--COM3.RX_TimeOut == 0)
			{
				if(COM3.RX_Cnt > 0)
				{
					for(i=0; i<COM3.RX_Cnt; i++)	TX3_write2buff(RX3_Buffer[i]);	//收到的数据原样返回
				}
				COM3.RX_Cnt = 0;
			}
		}
	}

上面是示例代码中main函数里的主循环,接下来我就简单分析一下代码。

首先是COM3,就是代表串口3的结构体,库函数里定义好的。

RX_TimeOut就是等待时间,在中断函数里(详情可以自行去库函数里看),接收到数据的时候就会把它设为5,然后在上面代码里是当这个等待时间大于5,我们进入一次第一层的if语句,接着如果减一之后它等于0了,我们进入第二层if语句。

RX_Cnt就是接收缓冲区里收到数据的大小,TX3_write2buff就是串口3的发送缓冲区,RX3_Buffer就是串口3的接收缓冲区,上面就是把收到的数据再发送回去。

由于我们的主循环是1ms执行一下这一坨代码,所以每个等待时间就是1ms,上面代码的意思就是如果串口收到数据了,那么我等它5ms,每收到一次数据,就会在中断函数里把等待时间刷新为5,我在main函数里每隔1ms把等待时间减1,如果我能够把它减到0,那么表示至少是5ms没有收到数据了,那我就把数据取出来发送回去。

上面听不明白没关系,我们只需要把这段代码复制下来,把最里面的一层if语句里的逻辑改改就能够自行处理接收到的数据了。

接下里就是最后一个问题。

串口的引脚。

每个串口至少有两组引脚可以供我们选择。

所以我们需要设置我们使用的是哪一组引脚。

我们需要包含一个头文件STC32G_Switch.h,坑人的是库函数手册里没有介绍这个头文件,我还是去翻官方示例代码的时候看到的。

我们使用这个

    UART3_SW(UART3_SW_P00_P01);

或者这个

    UART3_SW(UART3_SW_P50_P51);

就可以设置串口3的引脚了,其他串口只需要把上面函数名(实际上是宏定义)里的数字改掉就行,包括GPIO也是一样的。

然后记得给使用的GPIO配置一下,TXD就给推挽输出,RXD就给高阻输入,或者直接两个都设置为准双向口也可以。

最后的最后,串口输出的可能是乱码,这不一定是代码的问题,我们需要在Keil里改个设置。

其实官方手册里有建议这样设置,但是我在这个系列的第一篇环境配置的时候没有提这个,因为我当时没发觉有什么差别。

然而如果不把这个配置好的话,就算代码没问题也还是会出问题。

#include <STC32G.H>
#include "STC32G_GPIO.h"
#include "STC32G_Delay.h"
#include "STC32G_UART.h"
#include "STC32G_NVIC.h"
#include "STC32G_Switch.h"

void GPIO_Init(void){
    P0_MODE_OUT_PP(GPIO_Pin_1);
    P0_MODE_IN_HIZ(GPIO_Pin_0);
}

void UART_Init(void){
    COMx_InitDefine initer;
    initer.BaudRateDouble = DISABLE;
    initer.Morecommunicate = DISABLE;
    initer.UART_BaudRate = 115200;
    initer.UART_BRT_Use = BRT_Timer3;
    initer.UART_Mode = UART_8bit_BRTx;
    initer.UART_RxEnable = ENABLE;

    UART_Configuration(UART3, &initer);
    NVIC_UART3_Init(ENABLE, Priority_1);

    UART3_SW(UART3_SW_P00_P01);
}

void main(void){
    uint8 i = 0;
    WTST = 0;		//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    EAXSFR();		//扩展SFR(XFR)访问使能 
    CKCON = 0;      //提高访问XRAM速度
    
    GPIO_Init();
    UART_Init();
    EA = 1;
    
    PrintString3("Hello World\r\n");

    while(1){
        delay_ms(1);
        if(COM3.RX_TimeOut > 0){	//超时计数
			if(--COM3.RX_TimeOut == 0){
				if(COM3.RX_Cnt > 0){
					for(i=0; i<COM3.RX_Cnt; i++)	TX3_write2buff(RX3_Buffer[i]);	//收到的数据原样返回
				}
				COM3.RX_Cnt = 0;
			}
		}
    }
    return ;
}

顺带一提,STC的烧录软件里自带串口助手,我更爱STC了。

然后更屌的是我们可以直接使用printf,只需要把stdio.h的头文件加上就行了。

唯一需要改的地方在这里。

PRINTF_SELECT的宏定义改成我们要用的串口就行。

因为在库函数里帮我们重写了putchar函数,而printf底层用的就是putchar,所以等于变相改写了printf。


网站公告

今日签到

点亮在社区的每一天
去签到