51单片机的串行通讯程序

更新时间:2023-11-09 05:05:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

51 单片机的串行通讯

一、简介:

在中颖单片机2009年79F系列单片机的试用活动中,有幸成为一名试用者,在此首先 感谢该公司为电工们举办的此次公益活动,得到了一套79F32评估板和一个JET51 仿真器, 该仿真器能在Keil 下通过JTAG 口联机调试程序和编程,这对程序开发过程中的串行通讯功

能调试非常有用。

先上

评估套件的图片如下:

开发

由于常用的 51 单片机只有一个串行通讯口,且简易仿真器大都是通过串口来完成仿真 时的通讯功能的,还有很多51单片机是通过串口来ISP程序的(比如STC和NXP的51单片 机)。因而遇到有串行通讯的应用时,过去都采用直接把程序烧写到目标系统后然后联机测 试结果,有问题时重新改程序,重新下载测试来实现的(俗称盲调),俺过去都用AT89S52 加一个下载器来调试此类应用,因为它下载程序时,不占用串口,故串口可与目标系统直接 相连。中颖新推的8 位51 单片机具有JTAG 仿真功能,因而对于调试具有串行通讯外设的

应用系统带来了一个新的选择。

“51 单片机串行通讯”,这个话题我想大家初次看到,也许会觉得很简单,但您真的用 好串口的监视和可靠通讯两大主要功能吗?本文将结合本人的工作经验以中颖8 位51 增强

型SOC 单片机为平台讲述如何用好串行通讯功能,中颖单片机有双串口,非常适合有多种 通讯要求的应用,比如集散控制系统的中位机硬件平台,起到承上启下的作用。 时间仓促,如有不当或不对之处,还请各位不吝指正。 文档版本(V1.0)

此部分为笔

者为验证流 水灯自行 DIY 的元件

PDF 文件使用 \试用版本创建www.fineprint.cn 二、串口通讯的初始化与底层驱动程序: 51 单片机初始化串口有两个要点,

第一, 初始化串口的波特率

中颖 8051 中,波特率可以设置为系统时钟的分频或定时器的分频。 设置注意事项及规则如下:

A. 波特率不能等于系统时钟频率或定时器溢出率,只能为其分频值。

B. 当为串口方式1 或3 时,波特率发生器通过T2CON 的TCLK 和RCLK 来选择。TCLK 和RCLK 为1 时,选Timer2;TCLK 和RCLK 为0 时,选Timer1。

C. 当使用EUART1 时,不能使用Timer1 产生波特率。不管TCLK 和RCLK 为1或 0, 波特率发生器都为定时器 2。但是当TCLK 或RCLK 为1 时,波特率为TCLK 或RCLK 为0 时的波特率的二分频。

D. UART 工作在不同的工作方式下,波特率发生器有所不同,具体内容如下:

方式 0 时,波特率固定,波特率发生器为系统时钟的分频。当SM2=1时,波特率为系 统时钟的4 分频;当SM2=0 时,波特率为系统时钟的12 分频。当使用32.768K 并PLL 倍频后,系统时钟为8.192MHZ

当为方式 1 时,波特率可变,通过设置TCLK 和RCLK 来选择Timer1 或Timer2作为波 特率发生器。通过SMOD 位(二倍频控制位)来选择分频值。当SMOD=1 时,波特率为定时 器1 或2 溢出率/ 32 的二倍频,即16 分频;当SMOD=0 时,波特率为定时器1 或2 溢 出率的32 分频。

当为方式 2 时,波特率固定,波特率发生器为系统时钟的分频。通过SMOD 位(二倍频控 制位)来选择分频值。当 SMOD=1 时, 波特率为系统时钟/ 64 的二倍频, 即 32 分频; 当 SMOD=0时,波特率为系统时钟的64 分频。

当为方式 3 时,波特率可变,通过设置TCLK 和RCLK 来选择Timer1 或Timer2作为波 特率发生器。通过SMOD 位(二倍频控制位)来选择分频值。当SMOD=1 时,波特率为定时 器1 或2 溢出率/ 32 的二倍频,即16 分频;当SMOD=0 时,波特率为定时器1 或2 溢 出率的32 分频。 小结一下:

1.串口方式0 和方式2 为不可变波特率,方式1 和方式3 为可变波特率,可变值由T1 或 T2 控制

2.中颖单片机只用一个串口0 时,可选T1 或T2 作为波特率发生器。 3.中颖单片机使用两个串口时,T1 为串口0 波特率发生器,T2 为串口1的波特率发生器。 第二, 初始化串口的控制器 SCON和其它部分(比如中断和波特率加倍位等)

串口0 的控制寄存器为SCON,串口1 的控制寄存器为SCON1,其内容与51 的相同,但要注

意中颖51 的串口为与其它功能复用,因而要将管脚配置好方向,输入引脚配置好上拉电阻, 而输出引脚全部输出为高电平1,这样才能可靠的发送,发送完成后,状态符合串行通讯的 要求。

Demo 程序如下,采用定时器1作波特率发生器,也适用于普通51单片机使用。

串口初始化示例程如下,以中颖 79F32平台验证,在8.192M系统时钟时,波特率为9600

/**************************************************************************** void InitSys(void)

功能说明: 系统寄存器初始化

其他说明: Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0

PDF 文件使用 \试用版本创建www.fineprint.cn IEN0 EA EADC ET2 ES0 ET1 EX1 ET0 EX0

IEN1 EFCOF EI2C EPWM ESCM EHSEC ES1 EX2 ESPI 输入: 无 输出: 无

*****************************************************************************/ void InitSys(void) {

P0SS = Bin(00000000); //P0 as io P1SS = Bin(00000000); //P1 as io P0CR = Bin(00000000); P0PCR = Bin(00000000); P0 = Bin(00000000); P1CR = Bin(00000000); P1PCR = Bin(00000000); P1 = Bin(00000000); P2CR = Bin(00000000);

P2PCR = Bin(00000000); P2 = Bin(00000000);

//将P30,P31 初始化为串行通讯口 P3CR = Bin(00000010); P3PCR = Bin(00000001); P3 = Bin(00000011);

P4CR = Bin(00000000); P4PCR = Bin(00000000); P4 = Bin(00000000);

/*--------------------EUART初始化-------------------*/ TR0 = 0;

TR1 = 0; //stop timer1 TR2 = 0; //stop timer2

//---------------------------------------------------- TF0 = 0;

TF1 = 0;

// TMOD = Bin(00010001); //设置Timer1 为定时模式,工作方式一 (16bit,用于)

//定时器1 为8 位自装载,波特率发生器功能

TMOD = Bin(00100001); //设置Timer1 为定时模式,工作方式一 (16bit,用于)

PDF 文件使用 \试用版本创建www.fineprint.cn TL0 = LOBYTE(CLOCK_1MS);

TH0 = HIBYTE(CLOCK_1MS); // TL1 = LOBYTE(CLOCK_1MS); // TH1 = HIBYTE(CLOCK_1MS); TH1 = 0xe5; TL1 = 0xe5;

TF2 = 0;

// T2MOD = Bin(00000000); //设置Timer2 用于产生波特率(baudrate generator)

// T2CON = Bin(00110000);

//设置串口通讯方式为8位异步通讯,波特率可变。 SCON = Bin(01010000);

// RCAP2L = LOBYTE(UART_BAUDRATE); // TL2 = LOBYTE(UART_BAUDRATE); // RCAP2H= HIBYTE(UART_BAUDRATE); // TH2 = HIBYTE(UART_BAUDRATE); //---------------------------------------------------- TR0 = 1;

TR1 = 1; //start timer1 // TR2 = 1; //start timer2

//开启EUART和Timer0中断

IEN0 = Bin(00010010);

// IEN0 = Bin(00000010); //禁止串行中断

IEN1 = Bin(00000000); TI = 1; }

三、如何将程序中的变量内容输出到串行口

在程序调试过程中,出现了问题,用仿真器跟踪当然是最直接和高效的方法,但如果 没有仿真器,较好的方法是将相关的变量全部输出到串口,然后通过PC 机上的串口调试助 手软件来查看相关内容。通过对关键变量的查看结合源程序分析,很快能找到BUG所在。 软件中的变量常用的有好几种类型。那是否有通用的函数能完成将此变量的信息通过串 口送PC 来监视呢?C-51 有这样的现成函供供您调用。它就是我要隆重向您推荐的printf() 库函数,学过PC 机上的C 语言的同学对此应该比较熟悉。 使用printf前要做以下几个工作

1. 初始化串口波特率和模式,并置TI 为1;

2. 在源程序中包含头文件。

3. 如果是定时器1 作为波特率发生器,还可通过Keil-C51 软件仿真先在IDE 的虚拟 设备串口上看看printf()的工作情况

做好前面的工作后就可输出变量内容了。

PDF 文件使用 \试用版本创建www.fineprint.cn

字符型变量的输出用如下语句

printf(“字符变量X 的值为:%d\\n”,(unsigned int )ucTemp);其中ucTemp 为一个字节 型的变量

整型变量的输出用如下语句

printf(“整形变量X 的值为:%d\\n”,uiTemp); 其中uiTemp 为一个整形变量

长整型变量(4 字节)的输出用如下语句

printf(“长整形变量X 的值为:%ld\\n”,ulTemp); 其中ulTemp 为一个长整形变量 串口输出程序中的变量的 Demo程序如下(在中颖79F32 评估板上测试通过) #define uchar unsigned char #define uint unsigned int #define ulong unsigned long void main(void) {

uchar ucCount; uint uiCount; ulong ulCount; EA =0;

RSTSTAT = 0x00; //feed watchdog InitSys(); EA =1;

ucCount =0; uiCount = 0; ulCount = 0; while(1) {

printf(\

printf(\alue is %d\\n\printf(\alue is %d\\n\printf(\alue is %ld\\n\\n\printf(\alue is x\\n\printf(\alue is X\\n\printf(\alue is %l08X\\n\\n%ucCount++; uiCount++; ulCount++;

RSTSTAT = 0x00; //feed watchdog }

PDF 文件使用 \试用版本创建www.fineprint.cn }

测试过程中的电脑屏幕截图如下:

可在中颖79F32评估版上直接调试和验证的完整工程项目详见压缩包。 四、如何编程实现串口数据包的接收与发送 l 串口数据通讯,比较实用的模式有两种 4. 1 发送和接收都采用中断模式

发送和接收操作都要设数据缓冲区,占用内存较大,但CPU 的利用效率最高,无空耗 情况发生。

4.2 发送采用查询,接收采用中断

当设备要向外发送数据时,由于发送的数据的数量是已知的,因而在特定的波特率下,完 成发送操作的时间也是可以预测的。因而采用查询操作发送可简化发送数据过程,减小内存

本文来源:https://www.bwwdw.com/article/5byv.html

Top