(C51学习五)单片机与PC通过串口通信

1.开发步骤

2.串口模块

3.SBUF是什么

4.串口相应寄存器

5.给定波特率求定时值

6.代码实现


1.开发步骤

1.设置串口中断寄存器

2.求出给定波特率对应的T1定时器初始值(因为传统的C51是用T1定时器产生波特率的)

3.写程序


2.串口模块

什么是串口?串口就是COM口,串口是串行发送数据的,是一位位地发送数据位,常见的是9针串口。但在一般的C51学习版和开发版上都有集成CH340转换芯片,

使得用usb口就可以代替串口,所以用一般的学习板进行开发,只要插上usb线就可以进行串口测试。


3.SBUF是什么

SBUF是一个寄存器,作为一个缓冲区,当单片机准备接收数据时,会先把数据放到SBUF中,然后再接收。发送也是,当单片机准备发送数据时,会先把数据放到

SBUF中,再发送出去


4.串口相应寄存器

SCON串口控制寄存器(主要用方式1)

SM1,SM0:

SM0SM1工作方式功能波特率
00方式08位同步移位寄存器晶振频率 / 12
01方式110位UART可变
10方式211位UART晶振频率/32或晶振频率/64
11方式311位UART可变

SM2:----多机通信控制位(可以先不理)

多机通信是工作在方式2和方式3的,所以SM2主要用于方式2和方式3,多级通信时,SM2=1,当SM2=1时,只有当接收到的数据帧第9位(RB8)为1时,

单片机才把前八位数据放入自己的SBUF中,否则,将丢弃数据帧。当SM2=0时,不论RB8的值是什么,都会把串口收到的数据放到SBUF中。


REN:-----允许接收位

REN用于控制是否允许接收数据,REN=1时,允许接收数据,REN=0时,拒绝接收数据


TB8:-------是要发送的第9位数据位

在方式2和方式3中,TB8是要作为数据帧第9位被发送出去的,在多机通信中,可用于判断当前数据帧的数据是地址还是数据,TB8=0为数据,TB8=1为地址


RB8:-------接收到的第9位数据位

当单片机已经接收一帧数据帧时,会把数据帧中的第9位放到 RB8中。方式0不使用RB8,在方式2和方式3中,RB8为接收到的数据帧的第9位数据位。


TI:-----发送中断标志位

方式0中,不用管他。其他方式下,当发送数据完毕,硬件会将其置1,当 TI 被置1,会向CPU发送中断请求。我们记得要在中断服务程序中把 IT 置回0.


RI:-----接收中断标志位

当接受完一帧数据时,RI  由硬件置1,当RI 被置1,会向CPU请求中断。同样要在中断服务程序中把 RI 置回0。


PCON功率控制寄存器

这个寄存器只有一个位SMOD,在方式1,2.,3时,波特率都与SMOD有关,当SMOD=1时,波特率会增加一倍。复位时,SMOD变回0



5.给定波特率求定时值

串口中断要有定时器T1参加,因为C51是用定时器1来产生波特率的。

因此就需要给 定时器T1 设置初值。


首先,我们要选择一个合适的波特率,波特率关乎数据发送的快慢,一般我们选择9600b/s好了,你选2400也没问题。

一般我们会选择定时器的方式2(这里不是说上面的方式2,而是最大计数为256且自动重载定时器初值的方式)

使用这种方式是因为它能自动重载定时器初值,不用在中断服务程序中人工重设,可以减少误差。

下面给出公式:

Fosc:为晶振频率

(256-X):最终要求的是X,256出现的原因是定时器的方式2最大技术是256,如果是方式1,则是65536-X

最后把X化成16进制,高八位赋给 TH1,第八位赋给 TL1


例子:


或者可以直接下载一个51波特率计算器:



6.代码实现:

测试前提:首先要在PC机(电脑)上下载个串口助手,用于接收51单片机的数据。


C51发送数据到电脑:

#include <reg51.h>

typedef   unsigned char  uint8;
typedef   unsigned int   uint16;

uint8 Buf[]="hello world!\n";

void delay(uint16 n)
{
	while (n--);
}

/*波特率为9600*/
void UART_init(void)
{
    SCON = 0x50;        //串口方式1

    TMOD = 0x20;        // 定时器使用方式2自动重载
    TH1 = 0xFD;    //9600波特率对应的预设数,定时器方式2下,TH1=TL1
    TL1 = 0xFD;

    TR1 = 1;//开启定时器,开始产生波特率
}

/*发送一个字符*/
void UART_send_byte(uint8 dat)
{
	SBUF = dat;       //把数据放到SBUF中
	while (TI == 0);//未发送完毕就等待
	TI = 0;    //发送完毕后,要把TI重新置0
}

/*发送一个字符串*/
void UART_send_string(uint8 *buf)
{
	while (*buf != '\0')
	{
		UART_send_byte(*buf++);
	}
}

main()
{
	UART_init();
	
	while (1)
	{
		UART_send_string(Buf);
		delay(20000);
	}

}
效果:串口助手连接后会不停显示 hello world。(串口助手波特率要设成和单片机发送波特率一样,COM口也是)



电脑发送数据到单片机:

#include<reg52.h>
#define uchar unsigned char
#define uint  unsigned int
uchar buf;
void main(void)
{
SCON=0x50;//设定串口工作方式0101 0000
PCON=0x00;
TMOD=0x20;
EA=1;
ES=1;
TL1=0xfd;//波特率9600
TH1=0xfd;
TR1=1;
while(1);
}

//串行中断服务函数
void serial() interrupt 4
	{
	ES=0;		//暂时关闭串口中断
	RI=0;
	buf=SBUF;	//把收到的信息从SBUF放到buf中。
	switch(buf)
	{
	case 0x31: P1=0xfe;break;   //二进制 0011 0001  十进制 49 控制字符 1  16进制 0X31
	case 0x32: P1=0xfd;break;	 //1111 1101
	case 0x33: P1=0xfb;break;
	case 0x34: P1=0xf7;break;
	case 0x35: P1=0xef;break;   
	case 0x36: P1=0xdf;break;	
	case 0x37: P1=0xbf;break;
	case 0x38: P1=0x7f;break;
	}
	ES=1;		//重新开启串口中断

}

效果:当用电脑的串口助手向单片机发送数字1的时候,单片机会亮起LED0,以此类推。

  • 158
    点赞
  • 943
    收藏
    觉得还不错? 一键收藏
  • 33
    评论
好的,为了在C51单片机开发板上实现从PC端串口输入一串数字并在LCD上显示,我们需要进行以下步骤: 1. 首先,我们需要连接PC端和C51单片机开发板之间的串口通信线路。通常情况下,我们可以使用一根USB转串口线将PC端的USB接口连接到C51单片机开发板的串口接口。 2. 然后,我们需要在C51单片机开发板的代码中实现串口接收功能。在C51单片机中,我们可以使用 `SCON` 寄存器和 `TI`、`RI` 标志位来控制串口的发送和接收。具体实现方式可以参考C51单片机的相关手册和示例代码。 3. 接下来,我们可以在程序中使用 `lcd.h` 头文件提供的函数来控制LCD显示屏。在C51单片机开发板中,通常使用的是1602型字符LCD显示屏,其接口为16个引脚的并行接口。 4. 最后,我们可以将串口接收到的数据转换为整数,并使用 `lcd.h` 中提供的函数将其显示在LCD上。 下面是一份可能的C51单片机代码示例,可以实现从PC端串口接收一串数字并在LCD上显示: ```c #include <reg51.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "lcd.h" #define MAX_BUF_SIZE 16 sbit TX = P3^1; sbit RX = P3^0; void serial_init(void) { TMOD |= 0x20; SCON = 0x50; TH1 = 0xFD; TL1 = 0xFD; TR1 = 1; } char serial_read(void) { char c = 0; while (!RI); c = SBUF; RI = 0; return c; } void main(void) { char buf[MAX_BUF_SIZE] = {0}; int len = 0; int val = 0; // 初始化LCD和串口 lcd_init(); serial_init(); while (1) { // 从串口读取数据 if (RI) { buf[len++] = serial_read(); } // 如果读取到数据 if (len > 0) { // 如果读取到换行符或数据长度超过最大值 if (buf[len-1] == '\n' || len >= MAX_BUF_SIZE) { // 将读取到的数据转换为整数 val = atoi(buf); // 如果转换成功 if (val != 0 || buf[0] == '0') { // 在LCD上显示数字 lcd_puts("Value: "); lcd_putint(val); } // 清空缓存区 memset(buf, 0, sizeof(buf)); len = 0; } } // 延时一段时间 delay_ms(100); } } ``` 在这个示例代码中,我们使用了C51单片机的串口接口,并实现了 `serial_init()` 和 `serial_read()` 函数来进行串口初始化和接收。同时,我们还使用了 `lcd.h` 头文件提供的函数来控制LCD显示屏。在主循环中,我们不断从串口读取数据,并在读到换行符或数据长度超过最大值时进行数据转换和显示。注意,在C51单片机中,我们需要使用 `reg51.h` 头文件来访问寄存器和引脚。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 33
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值