嵌入式开发学习日志(硬件学习——51单片机UARTDay3)

一、UART基础概念

UART(Universal Asynchronous Receiver/Transmitter)        通用异步收发器;

参与通信的设备称为主机;

通信的本质是信息的传达;

1.1 通信方式

1.2 串行通信与并行通信 

  • 并行通信:通信双方之间有两根及以上的数据线传输信息传输速率较高,但会占用大量的芯片资源传输速率较高,但会占用大量的芯片资源.
  • 串行通信:通信双方之间只有一根数据线传输信息系统占用资源少,结构简单等优点。

USB(统一串口总线)

1.3 UART 

UART(串口)是一种通信方式,全双工串行通信方式

作为常用的串行通信方式,以TTL为例,串口通信在不同主机之间的数据格式为:

1、空闲时数据线为高电平;
2、发送时发送一个低电平表示起始位;
3、发送的第一个比特是最低位(最右边)bit0即LBS;
4、校验位分为奇校验,偶校验和无校验。                                                                                                  (1)奇校验是指确保数据位加上校验位中"1",1的总数为奇数;                                                     (2) 偶校验是指确保数据位加上校验位中"1",1的总数为偶数;
5.为保证下一个字节发送前的起始位能够表现出来,校验位之后发送一个停止位1。(将数据分隔);

数据传输速率:

串行通信用特率(bit per second)来描述数据传输的速率,记作bps。常见的波特率有1200、2400,4800,9600,115200等,表示每秒钟传输的比特数。

串行的异步通信与同步通信:

异步通信:指通信中两个字符(8位)之间的时间间隔是不固定的,而在一个字符内各位的时间间隔是固定的;
        收发双方的波特率必须是事先约定好的;

同步通信:要求发收双方具有同频同相的同步;
        用专用时钟信号线来控制时钟的节奏,以为例:

  • SDA(数据线)
  • SCL(时钟线):用于同步双方时钟的节奏,一般由发送方决定;
主机间通信时的电器物理问题:

        主机间通信无论采用并行还是串行方式,都无法避免一个物理现象:导线内阻不为零

        造成的电压衰减。以之前讨论的TTL电平为例,主机之间的距离会造成高电平在接收端出现衰减现象和串扰(指不同信号之间相互干扰导致信号失真)影响。

         1.TTL(Transistor-Transistor Logic)通常指的就是芯片引脚产生的电压,这个电压值跟选择的芯片有关,在51单片机系统下是5v;在2440下是3.3v等等。5vTTL通信距离通常被限制在10~20米之间,如果需要更远的距离,怎么解决呢?

        2. 为解决这个问题IEEE(Institute of Electrical and Electronics Engineers)颁布了RS232标准,其中规定了:

        逻辑高电平(逻辑1):在-3V到-15V之间

        逻辑低电平(逻辑0):在+3V到+15V之间                        

收发主机间有三根线,分别是收、发和地,因此RS232是全双工的。理论上RS232能够传输20~30米。

        3.同理RS485使用两根信号线(A和B)来传输数据,通过比较A和B之间的电压差来识别信息,电压范围分别为+7V到+12V和-7V到-12V。正电压表示高电平,负电压表示低电平。这种差分信号传输方式提高了抗干扰能力。RS485的传输距离可达1200米,适用于大范围的数据传输需求。由于采用的是压差,RS485在传输数据的某一时刻,两根线都要用到,所以它是半双工的。

二、串口通讯(51单片机——89C52)

硬件部分(USB下载电路)

 Windows表示串口为COMn;

2.1 SBUF寄存器

2.2 SCON寄存器与PCON寄存器

         STC89C51RC/RD+系列单片机的串行口设有两个控制寄存器:串行控制寄存器SCON波特率选择特殊功能寄存器PCON

2.2.1 SCON寄存器

2.2.2 PCON寄存器

xdata 的作用:不将内容放在芯片内部的RAM中,放在扩展的RAM中 

uart.c

#include "uart.h"
#include <reg52.h>
 
void init_uart(void)
{
	//串口接收
	SCON &= ~(3 << 6);
	SCON |= (1 << 6) | (1 << 4);
 
	//使参数生效
	PCON &= ~(1 << 6);
	PCON |= (1 << 7);
 
	//设置波特率,51单片机使用定时器1
	TMOD &= ~(0x0F << 4);
	TMOD |= (2 << 4);  //TMOD |= (1 << 5);前者更有可读性
	TL1 = 230;
	TH1 = 230;
	//打开定时器1
	TCON |= (1 << 6);
 
 
	//打开中断控制位及串口控制位
	IE |= (1 << 7) | (1 << 4);
 
}
 
//中断服务函数(TI RI都会导致中断)
//1.void uart_handler(void) interrupt 4
//{
//	if((SCON & (1 << 0)) == 1)
//	{
//		P2 = SBUF;//用LED显示
//		SCON &= ~(1 << 0);
//	}	
//}
//2.
xdata char rcv_buffer[32];
unsigned int pos = 0;
void uart_handler(void) interrupt 4
{
	if((SCON & (1 << 0)) == 1)
	{
		if(pos < 32)
		{
			rcv_buffer[pos++] = SBUF;
			rcv_buffer[pos] = 0;
		}
		SCON &= ~(1 << 0);
	}	
}
 
//发送(轮询)
void send_char(char ch)
{
	SBUF = ch;
	while((SCON & (1 << 1)) == 0);
	SCON &= ~(1 << 1);	
}
 
void send_buffer(const char *p, unsigned int len)
{
	while(len--)
	{
		send_char(*p++);	
	}
}
 
void send_str(const char *p)
{
	while(*p)
	{
		send_char(*p++);
	}
}
 
 

main.c

#include "uart.h"
#include "delay.h"
#include <reg52.h>
#include <string.h>
 
//int main(void)
//{
//	const char *s = "Hello World!";
//	char buffer[] = {0xAA, 0xBB, 0x00, 0x11};
//	init_uart();
//	while(1)
//	{
//		//send_char('A');
//		send_buffer(s,strlen(s));
//		//send_buffer(buffer, sizeof(buffer) / sizeof(*buffer));
//		delay(0xAFFF);	
//	}
//}
 
//int main(void)
//{
//	init_uart();
//	while(1)
//	{
//		if(pos != 0)
//		{
//			delay(0xAFFF);
//			send_buffer(rcv_buffer, pos);
//			pos = 0;	
//		}
//			
//	}
 
 
int main(void)
{
	//xdata char buffer[16];
	init_uart();
	while(1)
	{
		if(pos != 0)
		{
			delay(0xAFFF);
			if(strcmp(rcv_buffer, "Hello") == 0)
			{
				send_str("Hi");
			}
			else if(strcmp(rcv_buffer, "see u later") == 0)
			{
				send_str("bye");
			}
			pos = 0;	
		}
			
	}
}

三、MODBUS通信协议 

#include "uart.h"
#include "delay.h"
#include <string.h>
#include <stdio.h>
#include <reg52.h>
#include "led.h"
#include "digiter.h"
#include "timer.h"

#define DEV_ADDRESS 0x01

int parse(void)
{
	int ret = 0;
	if((unsigned char)rcv_buffer[0] == 0xAA && (unsigned char)rcv_buffer[6] == 0x0D)
	{
		P2 = 0;
		if((unsigned char)rcv_buffer[1] == DEV_ADDRESS)
		{
			unsigned char sum = 0;
			int i;
			for(i = 0;i < 5;++i)
			{
				sum += (unsigned char)rcv_buffer[i];
			}
			if(sum == (unsigned char)rcv_buffer[5])	//判断校验码是否一致
			{
				ret = rcv_buffer[2];				  //用于返回的功能码
			}
		}		
	}

	return ret;
}

void do_something(int n)
{
	switch(n)
	{
		case 1:
		led_on(rcv_buffer[4]);
		break;
		case 2:
		display(rcv_buffer[4]);
		break;
		case 3:
		while(1)
		{
			init_timer0();
			while(1)
			{
			
			}

		}
		break;
		default:
		break;
	}
}

int main(void)
{	 
	unsigned char sum1 = 0;
	int t = 0;
	init_uart();
	
	while(1)
	{
		if(pos != 0)
		{
			int ret;
			 delay(0xAFFF);
			 ret = parse();
			 do_something(ret);

			 if(ret != 0)
			 {
			 	xdata unsigned char buffer[10];
				memcpy(buffer, rcv_buffer,7);
				buffer[2] |= (1 << 7);
				for(t = 0;t < 5;++t)
				{
					sum1 += (unsigned char)buffer[t];
				}
				if(buffer[5] == rcv_buffer[5])
				{
					 buffer[5] = sum1;
					send_buffer(buffer,7);
				}
			 }
			 pos = 0;
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值