STC15系列单片机学习4:串口通讯

这篇具有很好参考价值的文章主要介绍了STC15系列单片机学习4:串口通讯。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、STC15系列单片机的串口个数

在使用单片机的串口前,得先知道所使用的单片机有几个串口,再结合你的硬件电路图来使用哪个串口。

以下是STC15各系列单片机的串口数量,STC15W4K32S4系列有4个串口

stc15w4k32s 串口通信,STC15系列单片机,单片机,51单片机,嵌入式硬件,学习

二、串口的工作模式

工作模式0:同步移位寄存器(官方建议初学者不学)

工作模式1:8位串口,波特率可变

工作模式2:9位串口,波特率固定(官方建议不学习)

工作模式3:9位串口,波特率可变

三、与串口工作相关的寄存器

以串口1为例,与串口1相关的寄存器

stc15w4k32s 串口通信,STC15系列单片机,单片机,51单片机,嵌入式硬件,学习

1、串行控制寄存器

STC15系列单片机串口1的控制相关的寄存器有SCON和PCON;

stc15w4k32s 串口通信,STC15系列单片机,单片机,51单片机,嵌入式硬件,学习

通过SCON寄存器中的SM0和SM1位来设置工作方式,设置如下表格所示,最常用的是工作方式1 

stc15w4k32s 串口通信,STC15系列单片机,单片机,51单片机,嵌入式硬件,学习

REN:串口接收使能位,REN = 1,启动串口接收,开始接收信息,REN = 0,禁止接收数据;

TB8:工作在9位UART模式才有效,也就是方式2和3,表示要发送的第9位;也就是奇偶校验位,8位UART不需要用这个位;

RB9:工作在9位UART模式才有效,也就是方式2和3,表示要接收的第9位;也就是奇偶校验位,8位UART不需要用这个位;

TI:发送中断请求标志位,在方式1,2,3中,在停止位开始发送的时候,单片机将TI位,置1,也就是TI = 1,向CPU发出中断申请,响应中断后,TI必须由软件清零,也就是用户要在代码中写上TI = 0;

RI:接收中断请求标志位,在方式1,2,3中,串行接收到停止位的终点时刻,单片机将RI位,置1,也就是RI = 1,向CPU发出中断申请,响应中断后,RI必须由软件清零,也就是用户要在代码中写上RI = 0;

电源控制寄存器PCON用来设置串口1的波特率是否加倍,PCON中与串口1相关的位只有SMOD和SMOD0

stc15w4k32s 串口通信,STC15系列单片机,单片机,51单片机,嵌入式硬件,学习

SMOD:波特率选择位,当SMOD = 1,串口波特率加倍;当SMOD = 0,波特率不加倍,默认是SMOD = 0;

SMOD0:帧错误检测有效控制位。这个位能决定SCON寄存器中SM0/FE位的功能,SMOD0 = 1时,SM0/FE位的功能是FE(帧错误检测),SMOD0 = 0时,SM0/FE位的功能是SM0功能,复位时SMOD0 = 0;

2、串行口数据缓冲寄存器SBUF

数据缓冲寄存器器,分为数据接收缓冲器数据发送缓冲器,它们可以同时工作,也就是说,串口可以同时发送数据和接收数据。

数据接收缓冲器只能读出,不能写入;

数据发送缓冲器只能写入,不能读出;

数据接收缓冲器与数据发送缓冲器的地址是一样的,比如

串口1的数据接收与发送缓冲器的地址都是99H,在官方头文件中定义的名字都是SBUF;

串口发送数据:

单片机只要执行了写SBUF命令,(汇编指令:MOV    SBUF, A)或者 (C语言指令SBUF = XX),要发送的数据(一个字节)就会装入相同的9位移位寄存器,前面8位是数据字节,第9位可以根据工作模式来设置,9位串口设置为TB的值,8位串口设置为1;

串口接收数据:

串口的接收急促器本身就是一个输入移位寄存器,串口在工作模式1,2,3,移位寄存器为9位,当一帧数据接收完毕,移位寄存器中的数据字节(前8位)装入数据接收缓冲器SBUF,第9位装入SCON寄存器的RB8位。当一帧数据从移位寄存器装入SBUF后,可立即开始接收下一帧数据,用户应该在下一帧数据接收结束前将数据从SBUF中取走,否则数据就被覆盖了。

3、辅助寄存器AUXR

stc15w4k32s 串口通信,STC15系列单片机,单片机,51单片机,嵌入式硬件,学习

官方推荐用定时器T2作为串口1的波特率发生器,那就从了他吧,相关的AUXR寄存器位是T2x12和S1ST2.

T2x12:定时器2速度控制位,T2x12 = 0,12T 模式,T2x12 = 1,1T 模式,

S1ST2:串口1选择哪个定时器作为波特率发生器控制位,S1ST2 = 0,选择定时1作为串口 1的波特率发生器,S1ST2 = 1,选择定时2作为串口 1的波特率发生器。默认S1ST2 = 1;

4、定时器2的寄存器T2H,T2L

定时器2的寄存器T2H和寄存器T2L是定时器用来保存重装时间。

5、与串口1中断相关的寄存器位ES,PS

stc15w4k32s 串口通信,STC15系列单片机,单片机,51单片机,嵌入式硬件,学习

EA:CPU的中断总开关控制位,EA= 1,使能中断,EA= 0,禁止所有中断;

ES:串行口中断允许控制位,ES = 1,允许串口中断;ES= 0,禁止串口中断;

stc15w4k32s 串口通信,STC15系列单片机,单片机,51单片机,嵌入式硬件,学习

 PS:串口1的中断优先级控制位,PS=0,串口1的中断优先级为0,最低优先级;PS= 1,串口1的中断优先级为1,最高优先级

6、控制串口1相关引脚的寄存器AUXR1

stc15w4k32s 串口通信,STC15系列单片机,单片机,51单片机,嵌入式硬件,学习

四、用户在程序中如何使用串口

以串口1为例,使用串口的步骤如下

1、设置串口1的工作模式,使用串行控制寄存器SCON中的SM0和SM1这两位来设置工作模式;

2、设置串口1的波特率,使用定时器2的寄存器T2H和T2L;

3、设置定时器2的速度1T还是12T,使用辅助寄存器AUXR中的T2x12位;

4、启动定时器2,通过设置T2R位为1,定时器2就开始计数;

5、设置串口1的中断优先级,并打开中断,打开中断需要打开PS、ES、EA这些控制位;

6、如果串口1是接收数据,将REN位设置为1就可以;如果串口1是发送数据,将数据送入SBUF就可以;

7、数据接收完成,标志位RI自动置1;数据发送完成,标志位TI自动置1;RI和TI都需要软件清0;

波特率的计算

串口1的波特率 = 定时器T2的溢出率 / 4;

STC15系列单片机我们一般用它工作在1T模式,这个通过AUXR来设置,

定时器2的溢出率 = SYSclk / (65536-[RL_TH2, RL+TL2]);

则串口1的波特率 = SYSclk / (65536-[RL_TH2, RL+TL2])/4

五、串口1工作模式1:8位UART,波特率可变

stc15w4k32s 串口通信,STC15系列单片机,单片机,51单片机,嵌入式硬件,学习

stc15w4k32s 串口通信,STC15系列单片机,单片机,51单片机,嵌入式硬件,学习

六、串口1的工作模式3: 9位UART,波特率可变

stc15w4k32s 串口通信,STC15系列单片机,单片机,51单片机,嵌入式硬件,学习

stc15w4k32s 串口通信,STC15系列单片机,单片机,51单片机,嵌入式硬件,学习

 

七、串口应用代码示例

程序示例2: 

#include <STC15.H> 
#include <intrins.h>

#define FOSC    11059200L

#define BAUD    115200
#define NONE_PARITY         0
#define ODD_PARTITY         1
#define EVEN_PARTITY        2
#define MARK_PARTITY        3
#define SPACE_PARTITY       4
#define PARITYBIT           EVEN_PARTITY

typedef unsigned char BYTE;
typedef unsigned int WORD;

bit busy;

BYTE flag = 0;

void SendDate(BYTE dat);
void SendString(char *s);



void main(void)
{
#if(PARITYBIT == NONE_PARITY)
    SCON = 0x50;//8位可变波特率
#elif(PARITYBIT == ODD_PARTITY)||(PARITYBIT == EVEN_PARTITY)||(PARITYBIT == MARK_PARTITY)
    SCON = 0xDA;//9位可变波特率,校验初始位为1
#elif(PARITYBIT == SPACE_PARTITY)
    SCON = 0xDa;//9位可变波特率,校验初始位为0
#endif
    
    T2L = (65536-(FOSC/4/BAUD));
    T2H = (65536-(FOSC/4/BAUD)) >> 8;
    AUXR = 0x14;//T2为1T模式,并启动定时器2
    AUXR |= 0x01;//选择T2作为串口1的波特率发生器
    
    ES = 1;//使能串口1中断
    EA = 1; //打开中断总开关
    
    while(1)
    {
        if(flag == 1)
        {
            SendString("STC15W4K\r\n");
            flag = 0;
        
        }  
    }
}

void Uart_ISR() interrupt 4
{
    if(RI)
    {
        RI = 0;//清除RI位
        flag = 1;      
    }
    if(TI)
    {
        TI = 0; //清除TI
        busy = 0; //清除忙标志位
    }
}


void SendData(BYTE dat)
{
    while(busy);//等待前面的数据发送完成
    ACC = dat;//获取校验位P,PSW.0
    if(P)
    {
    #if(PARITYBIT == ODD_PARTITY)
        TB8 = 0;//设置校验位为0
    #elif(PARITYBIT == EVEN_PARTITY)
        TB8 = 1;//设置校验位为1
    #endif       
    }
    else
    {
    #if(PARITYBIT == ODD_PARTITY)
        TB8 = 1;//设置校验位为1
    #elif(PARITYBIT == EVEN_PARTITY)
        TB8 = 0;//设置校验位为0
    #endif    
    }
    
    busy = 1;
    SBUF = ACC; //写数据到UART数据寄存器
}

void SendString(char *s)
{
    while(*s) //检查字符串结束标志
    {
        SendData(*s++); //发送当前字符
    }
}

程序实例2:文章来源地址https://www.toymoban.com/news/detail-849788.html

#include <STC15.H> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include <intrins.h>

/*------------------------------------------------
                   函数声明
------------------------------------------------*/


/*************	功能说明	**************

串口1全双工中断方式收发通讯程序。本例程使用11.0592MHZ时钟,如要改变,请修改下面的"定义主时钟"的值并重新编译。

串口设置为:115200,8,n,1.

通过PC向MCU发送数据, MCU收到后通过串口把收到的数据原样返回.

******************************************/

/*************	本地常量声明	**************/
//#define MAIN_Fosc		22118400L	//定义主时钟
#define MAIN_Fosc		11059200L	//定义主时钟
#define	RX1_Lenth		32			//串口接收缓冲长度
#define	BaudRate1		115200UL	//选择波特率


#define	Timer1_Reload	(65536UL -(MAIN_Fosc / 4 / BaudRate1))		//Timer 1 重装值, 对应300KHZ
#define	Timer2_Reload	(65536UL -(MAIN_Fosc / 4 / BaudRate1))		//Timer 2 重装值, 对应300KHZ

#define		S1_DoubleRate()		PCON |= 0x80
#define		S1_SHIFT()			SCON &= 0x3f
#define		S1_8bit()			SCON  = (SCON & 0x3f) | 0x40
#define		S1_9bit()			SCON  = (SCON & 0x3f) | 0xc0
#define		S1_RX_Enable()		SCON |= 0x10
#define		S1_USE_P30P31()		P_SW1 &= ~0xc0					//UART1 使用P30 P31口	默认
#define		S1_USE_P36P37()		P_SW1 = (P_SW1 & ~0xc0) | 0x40	//UART1 使用P36 P37口
#define		S1_USE_P16P17()		P_SW1 = (P_SW1 & ~0xc0) | 0x80	//UART1 使用P16 P17口
#define		S1_TXD_RXD_SHORT()	PCON2 |=  (1<<4)	//将TXD与RXD连接中继输出
#define		S1_TXD_RXD_OPEN()	PCON2 &= ~(1<<4)	//将TXD与RXD连接中继断开	默认
#define 	S1_BRT_UseTimer2()	AUXR |=  1
#define 	S1_BRT_UseTimer1()	AUXR &= ~1



/*************	本地变量声明	**************/
unsigned char	RX1_Buffer[RX1_Lenth];	//接收缓冲
unsigned char	TX1_Cnt;	//发送计数
unsigned char	RX1_Cnt;	//接收计数
bit	B_TX1_Busy;	//发送忙标志


/*************	本地函数声明	**************/



/**********************************************/
void main(void)
{
	B_TX1_Busy = 0;
	RX1_Cnt = 0;
	TX1_Cnt = 0;

	//S1_8bit();				//8位数据
    SCON  = (SCON & 0x3f) | 0x40;
      
	//S1_USE_P30P31();		//UART1 使用P30 P31口	默认
    P_SW1 &= ~0xc0;	

	AUXR &= ~(1<<4);	//Timer stop  波特率使用Timer2产生
	AUXR |= 0x01;		//串口1的波特率发生器使用Timer2
	AUXR |=  (1<<2);	//Timer2 set as 1T mode
	T2H = Timer2_Reload >> 8;
	T2L = Timer2_Reload;
	AUXR |=  (1<<4);	//Timer run enable

	REN = 1;	//允许接收
	ES  = 1;	//允许中断

	EA = 1;		//允许全局中断
	
	while (1)
	{
		if(TX1_Cnt != RX1_Cnt) //收到过数据
		{
			if(!B_TX1_Busy)	//发送空闲
			{
				B_TX1_Busy = 1;		//标志发送忙
				SBUF = RX1_Buffer[TX1_Cnt];	//发一个字节
				if(++TX1_Cnt >= RX1_Lenth)	TX1_Cnt = 0;	//避免溢出处理
			}
		}
	}
}



/********************* UART1中断函数************************/
void UART1_interrupt (void) interrupt 4
{
	if(RI)
	{
		RI = 0;
		RX1_Buffer[RX1_Cnt] = SBUF;		//保存一个字节
		if((++RX1_Cnt) >= RX1_Lenth)
        {
            RX1_Cnt = 0;	//避免溢出处理
        }            
	}

	if(TI)
	{
		TI = 0;
		B_TX1_Busy = 0;		//清除发送忙标志
	}
}
 

到了这里,关于STC15系列单片机学习4:串口通讯的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STC15系列单片机:定时器/计数器16位自动重装载模式

    STC15系列单片机内部有5个16位定时器/计数器,分别是T0、T1、T2、T3、T4。 定时器与计数器,东西还是同一个东西,只是用法和功效不一样,就好比黄瓜,既可以内服也可以外敷,黄瓜还是那个黄瓜,作用就不一样了。 就拿T0来说,T0用于定时,那T0就是定时器,如果T0用于计数

    2024年01月25日
    浏览(38)
  • STC8H系列单片机IAP实现不停电下载(通过串口)

    在使用串口往STC单片机烧录程序时,需要冷启动,先点击下载再上电。这样做有一定的缺点。首先,一些特殊的外围电路要求一直保持有电状态,有些客户需求我们能远程操控设备就可以升级程序,而不需要去现场断电设备。其次,频繁的断电上电操作也比较麻烦。 STC 单片

    2024年02月03日
    浏览(54)
  • STC15单片机-低功耗设计

    STC15省电模式(数据手册有介绍) STC15系列单片机可以运行3种省电模式以降低功耗,它们分别是: 低速模式 , 空闲模式 和 掉电模式 。 正常工作模式下,STC15系列单片机的典型功耗是2.7mA ~7mA,而掉电模式下的典型功耗是0.1uA,空闲模式下的典型功耗是1.8mA 低速模式由时钟分

    2024年02月05日
    浏览(67)
  • 【STC15单片机】动态数码管

    目录 点亮一位数码管 动态数码管 100s倒计时 动态数码管封装代码 段选:选中哪一位数码管 位选:选中的数码管要显示的内容 这是我对段选位选的理解,就是选中某个位置,赋值字形码,显示想要的图形 如果只想让第一个数码管显示,就只需要让com1 = 1即可,其他comx都=0 如

    2024年02月13日
    浏览(27)
  • 【STC15单片机】简单的矩阵键盘代码

    单片机型号说明:IAP15F2K61S2 新建工程时单片机型号选择 STC15F2K60S2 51单片机矩阵键盘代码 本程序烧写到51单片机应该是正常使用的,手头没有51开发板了,暂时没测试 这个程序烧写到15单片机,前两列按键不能正常使用 只需要在判断第一列按键那部分程序,前面加上P42 = 0;

    2024年02月05日
    浏览(64)
  • 蓝桥杯STC15F2K60S2单片机 CCP/PCA/PWM模块的学习与使用

    有道是 “一花独放不是春,万紫千红春满园” 我们不能只满足于 眼前所谓的 “够用、能用” 的少量知识,而不去深入学习探究,进而不慎封锁了自己的见识 和 更多 创新开发上的可能性。 曾经仅满足于学习了蓝桥杯单片机的三个外部晶振 定时器: 定时器0、1、2. 就认为完

    2024年02月08日
    浏览(36)
  • 学习笔记|串口通信的基础知识|同步/异步|RS232|常见的串口软件的参数|STC32G单片机视频开发教程(冲哥)|第二十集:串口通信基础

    百度百科:串口通信的概念 什么是通信? 例如U盘和电脑,我们电脑需要往U盘存东西,而U盘上只有四个触点,除去一个电源一个地,只剩下两个引脚了。此时我们坑定不能像点亮LED那样单纯的给他两个引脚上输出个高低电平就能写数据了对吧。总不至于输出一个高电平就能

    2024年02月07日
    浏览(39)
  • 基于STC15单片机的智能密码锁(矩阵按键输入)设计

    目录 一、项目背景 二、功能需求  三、功能组成 四、总结         智能门锁是一种基于现代智能化技术,与传统门锁进行比较的创新型的电子门锁产品。传统门锁通常采用钥匙旋转来开启门锁,但传统门锁存在钥匙遗失、易被复制等问题,特别是具有主动性质的人员如

    2024年02月03日
    浏览(34)
  • 微机课设 | 基于STC15单片机的简易数字密码锁设计

    在日常的生活和工作中,住宅与部门的安全防范、单位的文件档案、财务报表以及一些个人资料的保存多以加锁的办法来解决。若使用传统的机械式钥匙开锁,人们常需携带多把钥匙, 使用极不方便, 且钥匙丢失后安全性即大打折扣。在安全技术防范领域,具有防盗报警功能的

    2024年02月04日
    浏览(38)
  • 电脑通过串口助手和51单片机串口通讯

    今天有时间把电脑和51单片机之间的串口通讯搞定了,电脑发送的串口数据,单片机能够正常接收并显示到oled屏幕上,特此记录一下,防止后面自己忘记了怎么搞得了。 先来两个图片看看结果吧! 下面是串口3.c的文件全部内容: 下面是oled.h的全部内容: 下面是oled.c的全部内

    2024年02月07日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包