实验器材:F103开发板
在F103环境下进行UART通信实验和RS232通信实验
UART通信实验(通用异步收发器)
UART串口通信原理:
什么是串行通信?什么是异步通信?什么是全双工?
什么是串行通信?
相较于串行通信还有一种并行通信(最常用还是串行)
图中可以看出串行通信的传输线有一根,而并行的线有多根,串行是一位一位的发送数据,而并行是多位多位的发送数据,好比单车道和多车道的区别,并行通信的传输速率要比串行高,那是不是并行传输要比串行传输要好?
非也,非也,并行通信存在多根线,线与线之间会存在数据的干扰,布线难度加大,资源浪费,常用的还是串行通信
什么是异步通信?
同步通信相比较与异步通信多了时钟总线,时钟总线的作用就是保证收发双方的时间同步,
而异步通信是如何做到收发双方数据同步?这里的UART处理是波特率的设置(ulBaud)
波特率保证了收发数据时间上的同步,每秒发送多少个数据,每秒接受多少个数据。
常见的有9600,115200……显而易见数值越大发送的越快。
但是发送越快可能会存在数据的丢失。
波特率: 是衡量资料传送速率的指标。表示每秒钟传送的符号数(symbol)。一个符号代表的信息量(比特数)与符号的阶数有关。例如传输使用256阶符号,每8bit代表一个符号,资料传送速率为120字符/秒,则波特率就是120baud,比特率是120*8=960bit/s。这两者的概念很容易搞错
什么是全双工通信?
单工通信:数据只能发送,不能接受
半双工:数据可以发送,可以接受,但是发送和接受不能同时进行(一般只有一条线数据传输)
全双工:数据可以发送,可以接收,并且可以同时进行(一般是有两条线来传输,TX,RX)
UART的通信过程
如图:
1.数据协议规定,在空闲状态下,UART为高电平状态,发送一位的起始位逻辑0代表通信的开始
2.接着是发送数据位,数据位由5-8位数据位和一位奇偶校验组成
3.数据发送完成是停止位,代表一次通信的结束
4.数据发送完成后为空闲状态,即恢复为高电平状态,等待下一次的呼叫
(串口每次只能发送一个字节的数据,是为了减少传输中出现的错误,如果要发送多个字节的数据,则需要重复这一过程)
起始位: 先发出一个逻辑”0”的信号,表示传输字符的开始。
数据位: 数据位在起始位之后,它的个数可以是5-8位(先发低位后发高位)如:10101010,构成一个字符。通常采用ASCII码。从最低位开始传送,靠时钟定位。
奇偶校验位: 数据位加上这一位后,使得“1”的位数应为偶数(偶校验)或奇数(奇校验),以此来校验数据传送的正确性(可有可无,只能校验,不能纠错)
停止位: 它是一个字符数据的结束标志。可以是1位、1.5位、2位的高电平。 由于数据是在传输线上定时的,并且每一个设备有其自己的时钟,很可能在通信中两台设备间出现了小小的不同步。因此停止位不仅仅是表示传输的结束,并且提供计算机校正时钟同步的机会。适用于停止位的位数越多,不同时钟同步的容忍程度越大,但是数据传输率同时也越慢。
空闲位: 处于逻辑“1”状态,表示当前线路上没有数据传输。
波特率: 是衡量资料传送速率的指标。表示每秒钟传送的符号数(symbol)。一个符号代表的信息量(比特数)与符号的阶数有关。例如传输使用256阶符号,每8bit代表一个符号,资料传送速率为120字符/秒,则波特率就是120baud,比特率是120*8=960bit/s。这两者的概念很容易搞错。
实验功能:
如图所示:当我们连接好硬件后,打开串口通信软件设置好波特率等等,复位开发板
串口打印出请输入您的指令:………………
当我们输入0的时候开发板上的LED右移,LCD显示为LED右移颜色高亮,并且串口返回数据LED右移已打开………………
其他功能:
使用中断按键key1,key2,key3,key4操作LCD,并且如串口指令执行功能
key1,key3 菜单下滑
key2,key4菜单上滑
软件设计:
原理图:
uart.c文件
void USART2_Init(unsigned long ulBaud)
{
GPIO_InitTypeDef GPIO_InitStruct;//定义结构体(GPIO,USART,NVIC)
USART_InitTypeDef USART_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
// 允许GPIOA和USART2时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
// PA2-TX2复用推挽输出(端口配置)
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
/* PA3-TX2浮空输入(复位状态,可以省略)
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStruct); */
// 初始化USART2(波特率ulBaud,允许Rx和Tx,默认8个数据位,1个停止位,无校验)
USART_InitStruct.USART_BaudRate = ulBaud;//波特率
USART_InitStruct.USART_WordLength = USART_WordLength_8b;//数据位
USART_InitStruct.USART_StopBits = USART_StopBits_1;//停止位
USART_InitStruct.USART_Parity = USART_Parity_No;//(校验位:无)
USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//设置收发模式
USART_InitStruct.USART_HardwareFlowControl
= USART_HardwareFlowControl_None;//硬件流控制:无
USART_Init(USART2, &USART_InitStruct);//串口2初始化
USART_Cmd(USART2, ENABLE);//使能USART2
USART_ClearFlag(USART2,USART_FLAG_TC);//清除发送完成标志
USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);//开启USART2接受中断
NVIC_InitStruct.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;//主优先级
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;//子优先级
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;//中断使能
NVIC_Init(&NVIC_InitStruct);//中断初始化
}
// 发送字符
unsigned char USART_SendChar(USART_TypeDef* USARTx, unsigned char ucChar)
{
while(!USART_GetFlagStatus(USARTx, USART_FLAG_TXE));
USART_SendData(USARTx, ucChar);
return ucChar;
}
// 发送字符串
void USART_SendString(USART_TypeDef* USARTx, unsigned char* pucStr)
{
while(*pucStr != '\0')
USART_SendChar(USARTx, *pucStr++);
}
// 非阻塞接收字符
unsigned char USART_ReceiveChar_NonBlocking(USART_TypeDef* USARTx)
{
if(USART_GetFlagStatus(USARTx, USART_FLAG_RXNE))
return USART_ReceiveData(USARTx);
else
return 0;
}
// printf调用函数(使用MicroLIB)
int fputc(int ch, FILE *f)
{
return(USART_SendChar(USART2, ch));
}
注:使用printf打印的时候需要在MDK上勾选Use Micor LIB
#include "key.h"
#include "led.h"
#include "lcd.h"
#include "stdio.h"
#include "usart.h"
#include "stm32f10x_exti.h"
void LCD_Proc(void);
void LED_Proc(void);
void Key_Init(void);
void LED_Control(uint16_t LED,uint8_t LED_Status);
void USART2_Init(unsigned long ulBaud);
uint32_t TimingDelay = 1;
unsigned char ucSec,ucLed=1;
unsigned long ulTick_ms;
int col_flag=0;
unsigned int i;
int main(void)
{
SysTick_Config(72000); // 定时1ms(HCLK = 72MHz)
Key_Init();
LED_Init();
BUZ_Init();
STM3210B_LCD_Init(); //LCD的初始化
LCD_Clear(Cyan); //清屏配置颜色
LCD_SetTextColor(White); //字体颜色
LCD_SetBackColor(Cyan); //字体背景颜色
LED_Control(LEDALL,0);//控制所有LED灯默认关闭(0关闭,1打开)
USART2_Init(9600); //串口初始化,设置波特率9600
USART_SendString(USART2,"请输入您的指令:\r\n");
USART_SendString(USART2," 输入0:LED左移\r\n");
USART_SendString(USART2," 输入1:LED右移\r\n");
USART_SendString(USART2," 输入2:打开蜂鸣器\r\n");
USART_SendString(USART2," 输入3:关闭蜂鸣器\r\n\r\n");
while(1)
{
LCD_Proc();
LED_Proc();
}
}
void LED_Proc(void)
{
switch(col_flag)
{
case 1:
if(ulTick_ms > 300) //0.3S延时
{
ulTick_ms = 0;
ucLed >>= 1;
if(ucLed == 0)
ucLed =0x80; //LED右移函数
LED_Disp(ucLed);
}
break;
case 2:
if(ulTick_ms > 300) //0.3S延时
{
ulTick_ms = 0;
LED_Disp(ucLed);
ucLed <<= 1; //LED左移函数
if(ucLed ==0)
ucLed = 1;
}
break;
case 3:
LED_Control(LEDALL,0);
GPIO_ResetBits(GPIOB,GPIO_Pin_4);//打开蜂鸣器
break;
case 4:
LED_Control(LEDALL,0);
GPIO_SetBits(GPIOB,GPIO_Pin_4);
}
}
/*************************************
LCD中文显示需要做字库,在fonts.h文件内
*************************************/
//LCD中文显示
void LCD_Proc(void)
{
LCD_DisplayStringLine(Line1," 19");
LCD_DisplayproHZ(Line1, 4, 0);
LCD_DisplayproHZ(Line1, 5, 1);
LCD_DisplayproHZ(Line1, 6, 2); //嵌入式
if(col_flag==1)
LCD_SetBackColor(Blue);
LCD_DisplayStringLine(Line3," 1. LED");
LCD_DisplayproHZ(Line3, 5, 4);
LCD_DisplayproHZ(Line3, 6, 5); //右移
LCD_SetBackColor(Cyan);
if(col_flag==2)
LCD_SetBackColor(Blue);
LCD_DisplayStringLine(Line5," 2. LED");
LCD_DisplayproHZ(Line5, 5, 3);
LCD_DisplayproHZ(Line5, 6, 5); //左移
LCD_SetBackColor(Cyan);
if(col_flag==3)
LCD_SetBackColor(Blue);
LCD_DisplayStringLine(Line7," 3.");
LCD_DisplayproHZ(Line7, 3, 6);
LCD_DisplayproHZ(Line7, 4, 7);
LCD_DisplayproHZ(Line7, 5, 8);
LCD_DisplayproHZ(Line7, 6, 9); //蜂鸣器开
LCD_SetBackColor(Cyan);
if(col_flag==4)
LCD_SetBackColor(Blue);
LCD_DisplayStringLine(Line9," 4.");
LCD_DisplayproHZ(Line9, 3, 6);
LCD_DisplayproHZ(Line9, 4, 7);
LCD_DisplayproHZ(Line9, 5, 8);
LCD_DisplayproHZ(Line9, 6, 10); //蜂鸣器关
LCD_SetBackColor(Cyan);
}
//按键中断
void Key_Init(void)
{
EXTI_InitTypeDef EXTI_InitStructure;//定义结构体
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
//时钟配置
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
/* PA0和PA8浮空输入*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0|GPIO_PinSource8);
/* PB1和PB2浮空输入*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource1|GPIO_PinSource2);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);//打开PA0中断连接
EXTI_ClearITPendingBit(EXTI_Line0);//清除中断标志
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource8);//打开PA8中断连接
EXTI_ClearITPendingBit(EXTI_Line8);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource1);//打开PB1中断连接
EXTI_ClearITPendingBit(EXTI_Line1);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource2);//打开PB2中断连接
EXTI_ClearITPendingBit(EXTI_Line2);
EXTI_InitStructure.EXTI_Line = EXTI_Line0|EXTI_Line8|EXTI_Line1|EXTI_Line2;//选择中断线0,8,2,1
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//设置中断请求
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能中断线
EXTI_Init(&EXTI_InitStructure);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断优先级分组
//PA0
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//使能按键所在的外部中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//子优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道
NVIC_Init(&NVIC_InitStructure);
//PA8
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// PB1
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// PB2
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
//中断服务函数
void EXTI0_IRQHandler(void) //PA0
{
for(i=0x5ffff; i>0; i--);//延时
if(EXTI_GetFlagStatus(EXTI_Line0)!=RESET)
{
EXTI_ClearFlag(EXTI_Line0);
col_flag++;
if(col_flag>4)
col_flag=1;
}
}
void EXTI9_5_IRQHandler(void) //PA8
{
for(i=0x5ffff; i>0; i--);//延时
if(EXTI_GetFlagStatus(EXTI_Line8)!=RESET)
{
EXTI_ClearFlag(EXTI_Line8);
col_flag--;
if(col_flag<1)
col_flag=4;
}
}
void EXTI1_IRQHandler(void) //PB1
{
for(i=0x5ffff; i>0; i--);//延时
if(EXTI_GetFlagStatus(EXTI_Line1)!=RESET)
{
EXTI_ClearFlag(EXTI_Line1);
col_flag++;
if(col_flag>4)
col_flag=1;
}
}
void EXTI2_IRQHandler(void) //PB2
{ for(i=0x5ffff; i>0; i--);//延时
if(EXTI_GetFlagStatus(EXTI_Line2)!=RESET)
{
EXTI_ClearFlag(EXTI_Line2);
col_flag--;
if(col_flag<1)
col_flag=4;
}
}
//串口中断服务函数
void USART2_IRQHandler(void)
{
uint8_t temp;
if(USART_GetFlagStatus(USART2,USART_IT_RXNE)!=0)
{
temp=USART_ReceiveData(USART2);
USART_SendData(USART2,temp);
switch(temp)
{
case'0':
col_flag=1;
USART_SendString(USART2,":LED右移已打开\r\n\r\n");
break;
case'1':
col_flag = 2;
USART_SendString(USART2,":LED左移已打开\r\n\r\n");
break;
case'2':
//col_flag = 3; //太吵了,实验自己打开
USART_SendString(USART2,":蜂鸣器已打开\r\n\r\n");
break;
case'3':
col_flag = 4;
USART_SendString(USART2,":蜂鸣器已关闭\r\n\r\n");
break;
}
}
}
void SysTick_Handler(void)
{
ulTick_ms++;
if(ulTick_ms%1000 == 0) ucSec+=0;
}
LCD,LED,key初始化函数,以及中文显示请下载工程查看
完整工程下载
选择第11个工程