• 学习笔记|串口与PC通信的接线|移植驱动程序|串口通信实战|STC32G单片机视频开发教程(冲哥)|第二十一集(上):串口与PC通信


    1.串口与PC通信的接线

    上节试验是串口和电脑进行一个通信,用了一根USB转232的线,直接插到了我们这个板子上。今天详细解释一下是怎么样接线。
    在这里插入图片描述
    每一个TD和一个RXD代表一组端口,就是一组串口。
    看DIP40的管脚功能图:
    在这里插入图片描述
    TXD_几和RXD_几表示这是该组串口的第几个通道,1是默认省略的。通道是分时打开,也叫分时复用
    在这里插入图片描述
    MCU串口出来的信号都是TTL电平。
    TTL电平信号规定,+5V等价于逻辑“1”,0V等价于逻辑“0”(采用二进制来表示数据时)。这样的数据通信及电平规定方式,被称做TTL(晶体管-晶体管逻辑电平)信号系统。

    芯片与芯片之间的通讯:

    如果通信协议和电平都一样,直接TX和RX链接就可以通信。

    在这里插入图片描述

    芯片与电脑之间的通讯:

    电脑没有TXD跟RXD的这个接口(以前的电脑有232接口)
    在这里插入图片描述
    串口能直接和电脑USB通信吗?不能直接通信,因为电脑没有串口。需借助USB转TTL的工具。
    在这里插入图片描述
    它中间用了颗芯片,去做电平的转化或者协议的转化,芯片常见的有CH340、CP2102,电脑还需要另外的去装驱动。
    在这里插入图片描述
    推荐使用如上的官方工具。
    程序无需任何处理,抗干扰能力更强!

    一个USB工具可以转2个串口,代替2个。
    在这里插入图片描述
    四个端子分别是接到了P47、P50、P46、P51。
    在这里插入图片描述
    再看看USB转TTL的模块,学名是:一箭双雕之USB转双串口。需要根据官方介绍,刷成USB转双串口的功能。占用1个usb口,2路串口输出。
    S-RXD是STC-CDC1串口的发送脚,连接其它串口的接收脚。S-TXD是STC-CDC1串口的接收脚。连接其它串口的发送脚。
    S-RXD本质上是TX,S-TXD本质上是RX,这么标注是为了方便用户接线。
    在这里插入图片描述

    一般使用同一组串口。一箭双雕还有OLED接口,4个led的流水灯等等。
    在这里插入图片描述
    USB转232通讯线。板载232端口(DB9母头)和电平转换电路。考虑到传输距离和抗干扰性的问题,中间就可以考虑使用TTL转232,相互去转化。
    TTL转232程序上无需任何处理,但抗干扰能力增强。实际项目中,如果距离有一定要求,可以采用此方式。甚至485,422。只要逻辑电平能对得上,就可以互相连接。

    2.利用实验箱示例代码移植驱动程序

    1)查找试验箱里面和我们的功能最接近的程序。如:11-串口2中断模式与电脑收发测试
    在这里插入图片描述
    上节课也用串口2,是根据手册编写的代码,后期一定要灵活运用程序包。官方提供的程序包里面官方都已经测试好了,不用去熟悉每一个寄存器,只要按照代码包里的寄存器配好就可以使用了。
    代码包里每一个试验都已经做到了最简单,不用从几万行代码里去扣出几十行几百行你有用的代码,每一个小实验对应一个功能。本节讲串口2,可以直接移植例程。
    2)先测试示例程序是否正常运行。
    一定先试验测试,再移植。
    3)分析哪些代码与我们的功能有用。
    只移植对我们有用的东西。
    4)新建文件,开始移植。
    尽量避免大部分无用的手敲,只需要学会怎么去移植就可以。
    打开待参考的11-串口2中断模式与电脑收发测试代码包(C语言),再将上一节的16.串口2通信复制并更名为17.串口PC通信,打开工程,在其基础上进行移植。
    同时打开以上2个工程,屏幕右边方示例代码,左边打开我们要需要的工程。
    先从主函数开始看,提升指令速度等原工程里都有(见sys_init()),明显不需要设为准双向口。
    选择波特率这行初始化没有,应该有用,选中这行并复制到新工程内,示例模板里是放在端口初始化之后,我们也放在sys_init()初始化之后。

    最小工程

    把工程里不必要的东西清理一下,保留最小工程,如:

    #include "COMM/stc.h"		//调用头文件
    #include "COMM/usb.h"
    #include "seg_led.h"
    #include "key.h"
    #include "beep.h"
    #include "tim0.h"
    #include "exit.h"
    #include "adc.h"
    #include "ntc.h"
    #include "usart2.h"
    
    
    char *USER_DEVICEDESC = NULL;
    char *USER_PRODUCTDESC = NULL;
    char *USER_STCISPCMD = "@STCISP#";
    
    bit  TIM_10MS_Flag;			//10ms的标志位
    u16 Tme_CountDown = 0;		//全局变量
    
    void sys_init();	//函数声明
    void delay_ms(u16 ms);	//unsigned int
    
    
    void main()					//程序开始运行的入口
    {
    	sys_init();				//USB功能+IO口初始化
    	UART2_config(2);    // 选择波特率, 2: 使用Timer2做波特率, 1其它值: 无效.1
    
    	usb_init();				//usb库初始化
    	Timer0_Init();			//定时器0初始化
    	EA = 1;					//CPU开放中断,打开总中断。
    
    	while(1)		//死循环
    	{
    
    		if( TIM_10MS_Flag==1 )									//如果10ms到了
    		{
    			TIM_10MS_Flag = 0;									//清空标志位
    		}
    	}
    }
    
    void Timer0_Isr(void) interrupt 1
    {
    	static timcount = 0;
    
    	SEG_LED_Show();			//数码管刷新的
    
    	timcount++;				//1ms+1
    	if( timcount>=10 )		//如果这个变量大于等于10,10ms计数到达
    	{
    		timcount = 0;
    		TIM_10MS_Flag = 1;	//10ms时间到了
    	}
    }
    
    
    void sys_init()		//函数定义
    {
        WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
        EAXFR = 1; //扩展寄存器(XFR)访问使能
        CKCON = 0; //提高访问XRAM速度
    
    	P0M1 = 0x00;   P0M0 = 0x00;   //设置为准双向口
        P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
        P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
        P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
        P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
        P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
        P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
        P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
    
        P3M0 = 0x00;
        P3M1 = 0x00;
    
        P3M0 &= ~0x03;
        P3M1 |= 0x03;
    
        //设置USB使用的时钟源
        IRC48MCR = 0x80;    //使能内部48M高速IRC
        while (!(IRC48MCR & 0x01));  //等待时钟稳定
    
        USBCLK = 0x00;	//使用CDC功能需要使用这两行,HID功能禁用这两行。
        USBCON = 0x90;
    }
    
    
    void delay_ms(u16 ms)	//unsigned int
    {
    	u16 i;
    	do
    	{
    		i = MAIN_Fosc/6000;
    		while(--i);
    	}while(--ms);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97

    先对示例代码进行测试,复制E:\STC32\STC32G-DEMO-CODE-V9.6-20230425\COMM文件夹至待移植工程目录,并添加include文件路径,将成功编译后的文件载入开发板。下载时选择主频为22.1184。
    看一下示例程序里使用的引脚,在UART2_config(2)上跳转初始化,S2_S = 1; //UART2 switch to: 0: P1.0 P1.1, 1: P4.6 P4.7,选择的是P4.6和P4.7。
    正常运行时,板子无任何变化,选择USB转232所在的串口,再看一下程序里的波特率为115200(#define Baudrate2 (65536 - MAIN_Fosc / 115200 / 4)),常用的还有9600。无校验,停止位1。打开串口,发送数据后返回一模一样的数据。执行的主要代码段为:

        while (1)
        {
            if((TX2_Cnt != RX2_Cnt) && (!B_TX2_Busy))   //收到数据, 发送空闲
            {
                S2BUF = RX2_Buffer[TX2_Cnt];
                B_TX2_Busy = 1;
                if(++TX2_Cnt >= UART2_BUF_LENGTH)   TX2_Cnt = 0;
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    示例代码验证完,没有问题,可以移植。

    代码移植

    首先打开刚才的最小工程,然后选择波特率的这行复制好了,EA=1总中断开启。把PrintString2()函数也复制过来。初始化完成后,打印一个字符串。代码中的小红点是仿真时的断点,也可以做为每次编写代码的位置提示。
    再把while主循环部分的执行代码复制移植过来,放在10ms执行标识前,可以把USB下载的代码段取消注释,方便下载。
    转到UART2_config(2)的定义,看看详细定义方法。移植该功能代码前,将上节课的串口模块.C和.H文件中自编代码部分删除。
    首先函数需要先移植过来,添加声明,复制UART2_config函数定义,再讲其下的中断函数复制过来(除中断函数外,其他函数都需要声明才可以使用)。中断函数和上节代码一样,不详细讲解了。UART2_config里还有设置串口函数SetTimer2Baudraye,移植过来(声明并复制定义)。
    接下来在看看函数中的变量,以PrintString2为例,右击变量名称B_TX2_Busy,转向到定义文件,找到定义。
    如果想主函数中也能使用这些变量,需要在usart.h中重新定义,在变量名前加extern:

    extern u8  TX2_Cnt;    //发送计数
    extern u8  RX2_Cnt;    //接收计数
    extern bit B_TX2_Busy; //发送忙标志
    
    extern u8  RX2_Buffer[UART2_BUF_LENGTH]; //接收缓冲
    
    • 1
    • 2
    • 3
    • 4
    • 5

    这样在别的任意的.C文件中,引用头文件usart.h就可以调用这些变量。调用前需要在相应的.C文件前部增加变量声明(不赋初始值),如在usart.c中增加:

    #include "usart2.h"
    
    u8  TX2_Cnt;    //发送计数
    u8  RX2_Cnt;    //接收计数
    bit B_TX2_Busy; //发送忙标志
    
    u8  RX2_Buffer[UART2_BUF_LENGTH]; //接收缓冲
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    修改主时钟:#define MAIN_Fosc 22118400L //定义主时钟(精确计算115200波特率)。复制宏定义Baudrate2和UART2_BUF_LENGTH。至此,完成移植。

    编译提示错误:undefined identifier

    编译,提示错误:HARDWARE\USART\usart2.c(67): error C67: ‘T2_CT’: undefined identifier,没有定义。
    在示例模板中找一下T2_CT,右击转向定义,在stc32g.h头文件中,sbit T2_CT = AUXR^3;AUXR寄存器的第3位。手册中搜索AUXR:
    在这里插入图片描述
    地址在0X8E,按这个地址去找,如下:
    在这里插入图片描述
    不建议直接修改头文件(以前的代码都用同样的头文件),可以修改程序中的定义为T2CT,修改完后重新编译,下载进去(实验箱的代码里大部分都没有CDC串口,需要手动进入下载模式)。串口工具中发送文字,能够接收到回显文字,移植成功。
    以后的工程中如果用到3个串口,不要再跟着手册去敲,只需要把示例代码,下载到板子里去测试,没问题就可以移植过来了。实验箱中的代码基本上main.c就搞定了,实际做工程的时候,有串口2,NTC,有ADC外部中断,有定时器0等等,不可能全都放在demo.c里面。

  • 相关阅读:
    “蔚来杯“2022牛客暑期多校训练营4 M题: Monotone Chain
    2022年9月及10月
    如何将 Bootstrap CSS 和 JS 添加到 Thymeleaf
    爱奇艺开源的高性能网络安全监控引擎
    【MySQL学习】C++外部调用
    flatbuffer使用
    day15--使用postman, newman和jenkins进行接口自动化测试
    24年3月使用VS22编译Telegram Desktop
    华为机试 - 模拟商场优惠打折
    CentOS中使用Docker来部署Postgresql
  • 原文地址:https://blog.csdn.net/Medlar_CN/article/details/133770728