uart我们称为通用异步收发器(Universal Asynchronous Receiver/Transmitter)
在使用之前,我们先认识一下他的结构
我们可以看到,RX,TX,GND,在实际使用中还要加上VCC
引脚介绍
VCC:供电pin,一般是3.3v
GND:接地pin,一般可不接,但是为了接受数据的稳定,还是要接上
RX(Receive):接收数据pin,与第二个设备接TX
TX(Transmit):发送数据pin,与第二个设备接RX(一定要注意,经常有人插反)
设备间通信有3种模式:
单工(仅在一个方向)
全双工(两个设备同时发送和接收)
半双工(设备轮流发送和接收)
uart双向通信,可以实现全双工!
通信也分为同步和异步
同步通信:一方发送,另一方应答,否则不进行下一次传输
异步通信:一方发送,不考虑另一方是否收到,直接进行下一次传输
为了不让uart串口在传输数据时出错,设备间通信时会提前人为规定好速率(波特率)
常用波特率是9600和115200,意为在一秒内传输9600个或115200个bit位(0或1)
我随便想一个波特率行不行
当然不行,主要是因为
一,通信双方必须事先设定相同的波特率这样才能成功通信,如果发送方个接受方按照不同的波特率通信则根本收不到有效信息,因此波特率最好是大家熟知的而不是随意指定。
二,经过了长久的发展形成了共识,大家常用的是9600或115200。
下面放代码
8051
/*9600 11.0592mhz*/
void UART_Init()
{
SCON=0x40;
PCON |= 0x80;
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x20; //设置定时器模式
TL1 = 0xFD; //设定定时初值
TH1 = 0xFD; //设定定时器重装值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
}
void UART_SendByte(unsigned char Byte)//串口发送一个字节数据
{
SBUF=Byte;
while(TI==0);
TI=0;
}
void UART_Routine() interrupt 4
{
if(RI==1)//如果收到了数据
{
//这里加入自己想实现的功能
RI=0;
}
}
stm32代码,这里放江科大的代码,他做的功能比较多适合大家使用
#include "stm32f10x.h" // Device header
#include <stdio.h>
#include <stdarg.h>
uint8_t Serial_RxData;
uint8_t Serial_RxFlag;
void Serial_Init(void)//串口初始化
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);//开启串口1时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//开启gpioa时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);//配置gpioa9为复用推挽输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);//配置gpioa为上拉输入
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 9600;//9600波特率
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//禁用串口流控制
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;//RX,TX双模式
USART_InitStructure.USART_Parity = USART_Parity_No;//0奇偶校验位
USART_InitStructure.USART_StopBits = USART_StopBits_1;//1停止位
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//8数据位
USART_Init(USART1, &USART_InitStructure);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口1中断,读寄存器非空产生中断
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//选择串口1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//IRQ 通道使能
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//子优先级1
NVIC_Init(&NVIC_InitStructure);
USART_Cmd(USART1, ENABLE);
}
void Serial_SendByte(uint8_t Byte)//发送字节
{
USART_SendData(USART1, Byte);
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}
void Serial_SendArray(uint8_t *Array, uint16_t Length)//发送数组
{
uint16_t i;
for (i = 0; i < Length; i ++)
{
Serial_SendByte(Array[i]);
}
}
void Serial_SendString(char *String)//发送字符串
{
uint8_t i;
for (i = 0; String[i] != '\0'; i ++)
{
Serial_SendByte(String[i]);
}
}
uint32_t Serial_Pow(uint32_t X, uint32_t Y)//乘方
{
uint32_t Result = 1;
while (Y --)
{
Result *= X;
}
return Result;
}
void Serial_SendNumber(uint32_t Number, uint8_t Length)//发送数字
{
uint8_t i;
for (i = 0; i < Length; i ++)
{
Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0');
}
}
int fputc(int ch, FILE *f)//重定向printf
{
Serial_SendByte(ch);
return ch;
}
void Serial_Printf(char *format, ...)//重定向printf
{
char String[100];
va_list arg;
va_start(arg, format);
vsprintf(String, format, arg);
va_end(arg);
Serial_SendString(String);
}
uint8_t Serial_GetRxFlag(void)//获取接收标志位
{
if (Serial_RxFlag == 1)
{
Serial_RxFlag = 0;
return 1;
}
return 0;
}
uint8_t Serial_GetRxData(void)//获取接收数据
{
return Serial_RxData;
}
void USART1_IRQHandler(void)//串口一 中断服务函数
{
if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
{
Serial_RxData = USART_ReceiveData(USART1);
Serial_RxFlag = 1;
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}
}