找回密码
 立即注册
查看: 483|回复: 0

stc8h8k64u|UART串口通讯

[复制链接]
  • 打卡等级:偶尔看看I
  • 打卡总天数:18
  • 最近打卡:2025-12-10 00:23:34
已绑定手机

5

主题

15

回帖

117

积分

注册会员

积分
117
发表于 2025-11-13 13:55:38 | 显示全部楼层 |阅读模式

学习目标

  • 了解串口通信的基本概念
  • 掌握STC8H的串口通信原理
  • 掌握STC8H的串口通信编程
  • 学会使用逻辑分析仪调试串口

学习内容

什么是串口

串口是一种在数据通讯中广泛使用的通讯接口,通常我们叫做 <span class="ne-text">UART</span> (通用异步收发传输器Universal Asynchronous Receiver/Transmitter),其具有数据传输速度稳定、可靠性高、适用范围广等优点。在嵌入式系统中,串口常用于与外部设备进行通讯,如传感器、液晶显示屏、WiFi模块、蓝牙模块等。

串口通信中的 TXD(Transmit Data)和 RXD(Receive Data)是串口通信中的两个重要信号。

TXD是指串口发送端的数据信号,而RXD是指串口接收端的数据信号。在串口通信中,发送端把要发送的数据发送到TXD引脚上,接收端则通过RXD引脚来接收这些数据。

TXD和RXD信号的实现方式取决于使用的芯片或模块。一般来说,它们都是通过芯片或模块的串口功能来实现的,这需要将相应的引脚连接到芯片或模块的串口引脚上。

在发送数据时,需要将要发送的数据通过串口的发送缓冲区发送到TXD引脚上,接收端通过RXD引脚接收这些数据并放入接收缓冲区中。在接收端收到完整的数据后,可以通过相应的处理进行数据的解析和处理。

需要注意的是,TXD和RXD的电平标准也需要一致,一般常见的有TTL电平和RS232电平,如果不一致则需要进行电平转换。同时,在编写程序时也需要注意串口波特率、数据位、停止位等参数的设置,以保证通信的稳定和可靠。

**以下是STC8H的芯片引脚介绍图
image.png
**

其中有4组Uart通讯口:

image.png

串口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信号的电平有时会有所不同,因此在连接不同设备时需要注意电平的兼容性。
image.png

串口转USB

串口转 USB 是一种将串口信号转换为 USB 信号的设备。它通常被用于连接没有 USB 接口的设备(如单片机、传感器等)与计算机之间的通讯,使这些设备可以通过 USB 接口与计算机进行通信。

在使用串口转 USB 设备时,需要将其插入计算机的 USB 接口,并将串口连接到需要通信的设备上。在计算机中打开串口终端程序,设置串口参数(如波特率、数据位、停止位等),即可开始进行数据传输。在通信过程中,串口转 USB 设备将串口信号转换为 USB 信号,并将其发送到计算机上,或者将从计算机上接收到的 USB 信号转换为串口信号并发送到外部设备上。

串口转 USB 设备通常由一个 USB 转串口芯片和一个串口接口组成。常见的 USB 转串口芯片有 FTDI 和 CH340 等,它们提供了一组标准的串口接口,可以方便地连接到各种外部设备上。

总之,串口转 USB 设备是一种非常实用的工具,它可以帮助我们连接各种没有 USB 接口的设备,方便数据的传输和通讯。

image.png
STC8H核心板串口调试

  1. 原理图

    image.png

    • D+D-对应的usb口,和pc主机连接
    • P3.1P3.0对应的芯片
    • 采用CH340将串口和USB之间进行转换

    所以,我们在PC机上为什么会装串口驱动,主要是用来解析CH340转换后的消息,这样PC机就能认识了

    1. 使用库函数编写串口通讯逻辑

    需求:通过串口调试工具,发送消息给开发板,开发板原封不动的将消息传回。

    开发步骤:

    1. 新建项目
    2. 导入库函数
    3. 编写逻辑

    串口调试实现

    1. 新建项目。新建 <span class="ne-text">main.c</span>文件

    2. 导入函数库。拷贝以下函数库文件到项目目录:

      1. Config.h Type_def.h
      2. GPIO.hGPIO.c
      3. Delay.hDelay.c
      4. UART.hUART.c``UART_Isr.c
      5. NVIC.c NVIC.h
      6. Switch.h
    3. 代码编写(发送)

      #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);
      
          }
      }
      
  2. 代码编写(接收并回写)

    #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) && (--COM1.RX_TimeOut == 0))
            {        
                if(COM1.RX_Cnt > 0)
                {
                    // 收到数据了,on_uart1_recv();
                    on_uart1_recv();
                }
                // 处理完数据,将数据个数清零
                COM1.RX_Cnt = 0;
            }
        	// 注意这里delay代码的位置,属于while
            delay_ms(10);
        }
    }
    
  3. 调试

    image.png

    使用 STC-ISP调试工具进行调试。切换好串口助手,选择正确的串口,设置和代码中相同的波特率。

    通过发送区进行数据发送,通过接收区观察接收内容。

    串口调试重难点

    功能配置

    • 配置IO的工作模式:如果不配置工作模式,会导致串口不工作。(UART1的当前代码中的引脚 P3.0P3.1默认是准双向口,可以不配置,但是不要存在侥幸心理,导致其他的串口使用中没有配置准双向口)

    • 配置UART的串口工作模式 UART_Mode

      • UART_ShiftRight同步移位输出:按位传输,效率低,通常不用。
      • UART_8bit_BRTx** 8位数据,可变波特率:常用。发送和接收的数据为8位。**
      • UART_9bit 9位数据,固定波特率,即无法在运行时动态更改波特率。
      • UART_9bit_BRTx 9位数据,可变波特率:发送和接收的数据为9位。最后一位为奇偶校验位。
    • 配置UART的波特率 RaudRate:根据实际情况来定,波特率越高,传输越快,但是出现丢帧的概率越高。通常 115200就够用。单位是 bit/s</span>

    • 配置UART的波特率发生器 BRT_Use:系统提供了4个发生器,通常一一对应。

      • BRT_Timer1
      • BRT_Timer2
      • BRT_Timer3
      • BRT_Timer4
    • 配置UART是否接收 RxEnable:可以获取RXD接收的数据。

    • 配置UART波特率加倍 BaudRateDouble:默认不加倍,配置加倍会导致波特率是设定的双倍,过高会导致丢帧。

    • 配置UART中断 Interrupt和优先级 Priority:UART的数据收发是通过中断实现的,如果不配置,则无法对外发送数据,TXD和RXD不工作。

    • 配置UART的端口 P_SW:串口通道可以通过几组引脚来实现,但是需要指明是哪一组。

    中断开启

    由于uart中的发送是通过中断实现的,需要开启,但是STC8还提供了一个总的开关,如果总开关不打开,一样不起作用。

    EA = 1;

    引入依赖库

    image.png

    UART的接收与发送

    1. 关于接收

    接收是通过接收缓冲区进行接收。

    在死循环中,间隔一定时间到缓冲区中去取数据,有数据,说明就是接收了

    1. 关于发送

    发送是通过发送缓冲区进行发送。

    **发送提供了单个字节发送的API: **TX1_write2buff(byte)>

    **发送提供了字符串发送的API: **PrintString1(str)

    配置printf

    修改了 UART.hprintf输出串口配置为 UART1,才能通过 printf 打印日志

    打开UART.h头文件,保留用到的UART宏

    #define	UART1	1       //使用哪些串口就开对应的定义,不用的串口可屏蔽掉定义,节省资源
    //#define	UART2	2
    //#define	UART3	3
    //#define	UART4	4
    

指定 printf函数使用 UART1串口

#define	PRINTF_SELECT  UART1		//选择 printf 函数所使用的串口,参数 UART1~UART4

如果还是无法用printf打日志,要确保一下 UART_Isr.c已经添加到工程:
image.png

回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-4-6 22:41 , Processed in 0.101872 second(s), 44 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表