记录每次学习的过程,总结学习的内容,希望能给到自己和别人帮助。

嵌入式学习-STC-UART(串口)

串口

是一种在数据通讯中广泛使用的通讯接口,通常我们叫做UART (通用异步收发传输器Universal Asynchronous Receiver/Transmitter)

串口通信中的 TXD(Transmit Data)和 RXD(Receive Data)是串口通信中的两个重要信号。
TXD是指串口发送端的数据信号,而RXD是指串口接收端的数据信号。在串口通信中,发送端把要发送的数据发送到TXD引脚上,接收端则通过RXD引脚来接收这些数据。
TXD和RXD信号的实现方式取决于使用的芯片或模块。一般来说,它们都是通过芯片或模块的串口功能来实现的,这需要将相应的引脚连接到芯片或模块的串口引脚上。
在发送数据时,需要将要发送的数据通过串口的发送缓冲区发送到TXD引脚上,接收端通过RXD引脚接收这些数据并放入接收缓冲区中。在接收端收到完整的数据后,可以通过相应的处理进行数据的解析和处理。
需要注意的是,TXD和RXD的电平标准也需要一致,一般常见的有TTL电平和RS232电平,如果不一致则需要进行电平转换。同时,在编写程序时也需要注意串口波特率、数据位、停止位等参数的设置,以保证通信的稳定和可靠。

串口TTL通讯协议

串口TTL(Transistor-Transistor Logic)是一种串口通信协议,使用TTL电平来进行串口数据传输。它主要用于嵌入式系统、传感器、模块等设备之间的数据通信。
串口TTL主要包括两个信号线:TX(Transmit,发送)和RX(Receive,接收)。TX线是串口TTL的输出线路,用于将数据从串口设备发送出去;RX线是串口TTL的输入线路,用于接收数据到串口设备。
串口TTL使用的是异步串行通信协议,其数据传输的原理是将数据分成一定的数据帧,在数据帧的首尾各加上一个起始位和停止位,用于确定每个数据帧的开始和结束位置。此外,串口TTL通信协议还规定了数据位的长度和奇偶校验位。
串口TTL通常有不同的波特率(Baud Rate)可供选择,波特率是指每秒钟传输的数据位数,通常表示为 bps(bits per second),比如 9600 bps、115200 bps 等等。波特率的设置必须要保证发送和接收设备的波特率一致,否则会导致通信失败。
需要注意的是,串口TTL使用的是TTL电平,其电压范围是0~5V,不同的设备的串口TTL信号的电平有时会有所不同,因此在连接不同设备时需要注意电平的兼容性。
在这里插入图片描述

先配置IO工作模式,再配置串口信息

中断开启(重要,很多人忘记开启这个一直找不到原因)
由于uart中的发送是通过中断实现的,需要开启,但是STC8还提供了一个总的开关,如果总开关不打开,一样不起作用。

EA = 1;

UART的接收与发送

  1. 关于接收
    接收是通过接收缓冲区进行接收。
    在死循环中,间隔一定时间到缓冲区中去取数据,有数据,说明就是接收了
  2. 关于发送
    发送是通过发送缓冲区进行发送。
    发送提供了单个字节发送的API: TX1_write2buff(byte)
    发送提供了字符串发送的API: PrintString1(str)
    在这里插入图片描述

UART的4组通讯口

Uart通讯口有4组:
在这里插入图片描述

接发逻辑

接收逻辑:

(使用不同串口组的话,修改COM 例如COM2 COM3)

if(COM1.RX_TimeOut > 0) {
    //超时计数
    if(--COM1.RX_TimeOut == 0) {
        if(COM1.RX_Cnt > 0) {
            for(i=0; i<COM1.RX_Cnt; i++)	{
                // RX1_Buffer[i]存的是接收的数据,写出用 TX1_write2buff
                // TODO: 做具体的逻辑 on_uart1_recv
            }
        }
        COM1.RX_Cnt = 0;
    }
}

在这里插入图片描述

发送逻辑:

(使用不同串口组的话,修改TX 例如TX2 TX3 修改PrintString 例如PrintString2,PrintString3)

TX1_write2buff(xx);// 写一个byte
PrintString1(""); // 写字符串

在这里插入图片描述

示例代码1:UART的发送

开启中断(全局)必须要写!EA = 1;

#include	"Config.h"
#include	"GPIO.h"
#include	"UART.h"
#include	"Delay.h"
#include	"NVIC.h"
#include	"Switch.h"

/*************	功能说明	**************
双串口全双工中断方式收发通讯程序。

通过PC向MCU发送数据, MCU收到后通过串口把收到的数据原样返回, 默认波特率:115200,N,8,1.

通过开启 UART.h 头文件里面的 UART1~UART4 定义,启动不同通道的串口通信。
******************************************/

/******************* IO配置函数 *******************/
void	GPIO_config(void)
{
    GPIO_InitTypeDef	GPIO_InitStructure;		//结构定义

    GPIO_InitStructure.Pin  = GPIO_Pin_0 | GPIO_Pin_1;		//指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7
    GPIO_InitStructure.Mode = GPIO_PullUp;	//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
    GPIO_Inilize(GPIO_P3,&GPIO_InitStructure);	//初始化
}

/***************  串口初始化函数 *****************/
void	UART_config(void)
{
    COMx_InitDefine		COMx_InitStructure;					//结构定义

    COMx_InitStructure.UART_Mode      = UART_8bit_BRTx;	//模式, UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTx
    COMx_InitStructure.UART_BRT_Use   = BRT_Timer1;			//选择波特率发生器, BRT_Timer1, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2)
    COMx_InitStructure.UART_BaudRate  = 115200ul;			//波特率, 一般 110 ~ 115200
    COMx_InitStructure.UART_RxEnable  = ENABLE;				//接收允许,   ENABLE或DISABLE
    COMx_InitStructure.BaudRateDouble = DISABLE;			//波特率加倍, ENABLE或DISABLE
    UART_Configuration(UART1, &COMx_InitStructure);		//初始化串口1 UART1,UART2,UART3,UART4
    NVIC_UART1_Init(ENABLE,Priority_1);		//中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
    
    UART1_SW(UART1_SW_P30_P31);		//UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17,UART1_SW_P43_P44
}


/**********************************************/
void main(void)
{

//    EAXSFR();		/* 扩展寄存器访问使能 */
    GPIO_config();
    UART_config();
    EA = 1;

   // TX1_write2buff(0x23);	// #
  //  printf("STC8H8K64U UART1 Test Programme!\r\n");	//UART1发送一个字符串
    //PrintString1("STC8H8K64U UART1 Test Programme!\r\n");	//UART1发送一个字符串

    while (1)
    {

        TX1_write2buff(0x2F); 
        delay_ms(250);
        delay_ms(250);
        delay_ms(250);
        delay_ms(250);
		  	PrintString1("STC8H8K64U UART1 Test Programme!\r\n");	
			  delay_ms(250);
        delay_ms(250);
        delay_ms(250);
        delay_ms(250);

    }
}

重点代码说明:
1.在17-24会配置IO工作模式。示例代码的是结构体模式,P3.0和P3.1引脚设置为准双向口模式
2.在26-40行会进行串口初始化函数,其中:
–34行的UART_BaudRate是波特率,一般不修改,波特率越高,传输越快,但是失误率会高点
–36行的UART_Configuration参数,是根据你的引脚所在的通讯口分组选择是uart1,2,3,4
–39行的UART1_SW(UART1_SW_P30_P31) 则还是根据你的引脚所在的通讯口分组选择
3.52-54则是三种发送的方式
–注意:如果想用printf的话,需要配置,其余两种可以直接使用:PrintString1( )和TX1_write2buff( )

想要使用printf() ,需要修改uart.h文件低9行的 uart2 ,改成uart1
可以得到串口返回的信息

在这里插入图片描述

示例代码2:UART的接收并回写

提前说明:
标识符需要最先声明或定义
keil中 各种的声明必须在main的最前面,其他方法名的前面,不然会报错,编译器无法识别标识符,一定要在最前面声明或定义。
例如:

void main(){
  int a;
  int b;
  func(){}
}

而不能在其他方法的后面(以下为错误写法)

void main(){
  int a;
  func(){}
  int b;
}

开启中断(全局)必须要写!EA = 1;

#include "Config.h"
#include "GPIO.h"
#include "UART.h"
#include "Delay.h"
#include "NVIC.h"
#include "Switch.h"

void GPIO_config(void) {
    GPIO_InitTypeDef	GPIO_InitStructure;		//结构定义
    GPIO_InitStructure.Pin  = GPIO_Pin_0 | GPIO_Pin_1;		//指定要初始化的IO, P30, P31
    GPIO_InitStructure.Mode = GPIO_PullUp;	//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
    GPIO_Inilize(GPIO_P3, &GPIO_InitStructure);//初始化
}

void UART_config(void) {
    COMx_InitDefine		COMx_InitStructure;					//结构定义
    COMx_InitStructure.UART_Mode      = UART_8bit_BRTx;	//模式, UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTx
    COMx_InitStructure.UART_BRT_Use   = BRT_Timer1;			//选择波特率发生器, BRT_Timer1, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2)
    COMx_InitStructure.UART_BaudRate  = 115200ul;			//波特率, 一般 110 ~ 115200
    COMx_InitStructure.UART_RxEnable  = ENABLE;				//接收允许,   ENABLE或DISABLE
    COMx_InitStructure.BaudRateDouble = DISABLE;			//波特率加倍, ENABLE或DISABLE
    UART_Configuration(UART1, &COMx_InitStructure);		//初始化串口1 UART1,UART2,UART3,UART4

  	NVIC_UART1_Init(ENABLE,Priority_1);		//中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3

    UART1_SW(UART1_SW_P30_P31);		//UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17,UART1_SW_P43_P44
}

void on_uart1_recv() {
    u8 i;
    // RX_Cnt收到的数据个数(字节u8 - unsigned char)
    // 将收到的数据, 按字节逐个循环
    for(i=0; i<COM1.RX_Cnt; i++) {
        u8 dat = RX1_Buffer[i]; //  1 1 1 1  0 0 0 0 -> 0xF0
        TX1_write2buff(dat);	//收到的数据原样返回
    }
}
/**
开启串口调试,接收数据,把收到的数据原样返回

**/
void main() {
    // 初始化IO
    GPIO_config();

    // 初始化UART
    UART_config();

    // 开启中断(全局)必须要写!
    EA = 1;

    // 写一个字节
  //  TX1_write2buff(0x23);
	// 通过PrintString1输出字符串
   // PrintString1("STC8H8K64U UART1 Test Programme!\r\n");	//UART1发送一个字符串
    // 通过printf输出字符串
   // printf("STC8H8K64U UART1 Test Programme!\r\n");	//UART1发送一个字符串

     while(1) {
        // 超时计数
        // 一旦收到了一个字节数据,RX_TimeOut会初始化一个值(例如:5)
        if(COM1.RX_TimeOut > 0) {
            //超时计数
            if(--COM1.RX_TimeOut == 0) {
                if(COM1.RX_Cnt > 0) {
                    for(i=0; i<COM1.RX_Cnt; i++)	{
                        // RX1_Buffer[i]存的是接收的数据,写出用 TX1_write2buff
                        // TODO: 做具体的逻辑 on_uart1_recv
											TX1_write2buff(RX1_Buffer[i]);
                    }
                }
                COM1.RX_Cnt = 0;
            }
        }
        // 注意这里delay代码的位置,属于while
        delay_ms(10);
    }
}

重点代码说明:
1.在9-12会配置IO工作模式。示例代码的是结构体模式,P3.0和P3.1引脚设置为准双向口模式
2.在15-27行会进行串口初始化函数,其中:
–19行的UART_BaudRate是波特率,一般不修改,波特率越高,传输越快,但是失误率会高点
–22行的UART_Configuration参数,是根据你的引脚所在的通讯口分组选择是uart1,2,3,4
–26行的UART1_SW(UART1_SW_P30_P31) 则还是根据你的引脚所在的通讯口分组选择
3.62-74,接收是通过接收缓冲区进行接收。在死循环中,间隔一定时间到缓冲区中去取数据,有数据,说明就是接收了
其中:RX1_Buffer是一个函数,通常用于在C语言中处理缓冲区。

在这里插入图片描述

凡心所向,素履以往,生如逆旅,一苇以航。

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐