嵌入式系统原理及应用--刘存良老师主讲 USART之轮询方式讲解

咕咕咕~~~十分不好意思以至于自觉发出鸽子的声音,前段时间状态不太好,需要些时间打理QAQ ~

1、要点(即区分于其他方式的特点)

在主程序中通过不断查询(while语句)来判断是否发送数据,如下图:
在这里插入图片描述

2、实验过程

打开程序后,编译,将程序烧到核心板内,打开串口调试程序,调好各参数后打开串口,将核心板的按键拨到NC端,按下复位键,则出现视频中的现象。(本篇博客里没有放视频,放个视频太麻烦了=_=)

3、代码分析

整个代码如下:

//基本的USART实验
//通过USART1发送数据,PC机上运行串口调试助手软件接收字符
//如果串口没有显示正确的输出,请检查Target/Code Generation中的Use MicroLIB项是否被选择。

#include "stm32f10x.h"
#include 

void RCC_Configuration(void);
void GPIO_Configuration(void);
void USART_Configuration(void);
int fputc(int ch, FILE *f);/*重定向,修改一下选中Use MicroLIB ,
														 需要在 Target/Code Generation选中Use MicroLIB 
														 才能使用printf*/
void delay_nms(u16 time);//延时子程序

int main(void)
{
	RCC_Configuration();
	GPIO_Configuration();

	USART_Configuration();

	USART_ClearFlag(USART1,USART_FLAG_TC);	//清发送结束位,在发送第1位数据之前需要清除USART_FLAG_TC标志,
	//否则容易造成第一个数据发送不出去
	while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET);
	USART_SendData(USART1, 'A'); 	                              //向发送数据寄存器写一个字节
	while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET);
	USART_SendData(USART1, 'B');
	while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET);
	printf("\r\n");								                              //发送回车换行
	while(1)
	{		                                                        //PA8连接到了蜂鸣器上,程序运行时,蜂鸣器“嗒嗒”作响
		GPIO_SetBits(GPIOA,GPIO_Pin_8);                           //PA8置位 
		delay_nms(200);
		GPIO_ResetBits(GPIOA,GPIO_Pin_8);                         //PA8清零
		delay_nms(200);
		while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET);
		printf("青岛大学物联网工程系欢迎您!\n");
//		printf("新大陆教育!\n");
	}
}

void RCC_Configuration(void)
{
	//SystemInit();
  
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能GPIOA的时钟	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1的时钟, USART1挂接到APB2上。其他USART2-5挂接到APB1上
}
void GPIO_Configuration(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;        					//声明GPIO初始化结构变量。
	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_10; 					//配置管脚PA10/USART1_RX 
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN_FLOATING;//浮空输入
	GPIO_Init(GPIOA, &GPIO_InitStructure);      					//初始化PA10
	
	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_9; 					//配置管脚PA9/USART1_TX
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP; 			//IO口配置为复用输出口
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
	GPIO_Init(GPIOA, &GPIO_InitStructure); 								//初始化PA9	
	
	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_8; 					//配置管脚8
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP; 		//IO口配置为推挽输出口
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 		//工作频率50MHz
	GPIO_Init(GPIOA, &GPIO_InitStructure); 								//初始化PA8

}
 
void USART_Configuration(void)
{
	USART_InitTypeDef USART_InitStructure;
	
	USART_InitStructure.USART_BaudRate   = 115200;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;	
	USART_InitStructure.USART_StopBits   = USART_StopBits_1;
	USART_InitStructure.USART_Parity     = USART_Parity_No;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode       = USART_Mode_Tx;
	USART_Init(USART1, &USART_InitStructure); //初始化串口
	
  USART_Cmd(USART1, ENABLE); //启动USART
}


int fputc(int ch,FILE *f)
{
	if(ch=='\n') //newline, 0x0D
	{
		while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET);
		USART_SendData(USART1,'\r'); // carriage return, 0x0A
	}
	while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET);
	USART_SendData(USART1, ch);        
  return ch;
}

void delay_nms(u16 time)//延时子程序
{  u16 i=0;  
   while(time--)
   {  i=12000;  //自己定义
      while(i--) ; 
   }
}


首先,从全局上来看,main.c文件中中有main函数、以及main函数中调用的RCC_Configuration、GPIO_Configuration、USART_Configuration函数。
众所周知,执行一个程序都是从main函数开始执行。而看main函数中,从上而下看:

(1)第一句是RCC_Configuration();

而看RCC_Configuration()的定义:

由STM32固件库参考手册可知,其完成的作用就是开启GPIOA的时钟,之后开启AB2的时钟,也就是USART1的时钟,这时的USART1挂接到APB2上,其他USART2-5挂接到APB1上。

(2)第二句是GPIO_Configuration();

而看GPIO_Configuration()的定义:

首先声明GPIO初始化结构变量,然后配置管脚PA10/USART1_RX,由M3核心模块图里可知:

PA10和USART1_RX是复用一个管脚的,PA9是和USART1_TX是复用一个管脚的。

之后下一句代码是将模式设置成浮空输入,接着初始化PA10,由STM32固件库文件可知:

包括引脚定义、速度、模式等。

同样的,下面代码配置并初始化管脚PA9和管脚8.

(3)main函数的第三句代码是:USART_Configuration();其定义如下:

首先声明GPIO初始化结构变量,然后将波特率设置为115200,并且有8位的数据位,有一位停止位,没有校验位,并且设置成无硬件数据流控制,即RTS和CTS都没有使能。接着设置成TX模式,即发送模式,最后初始化串口,启动USART。

(4)main函数的第四句代码是:USART_ClearFlag(USART1,USART_FLAG_TC);

即清发送结束位,在发送第1位数据之前需要清除USART_FLAG_TC标志,否则容易造成第一个数据发送不出去。

(5)main函数的其余代码有如下分析:

其中轮询方式区别于其他方式的代码如下:
while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET);
这句代码的作用是一直查询是否可以发送,如果可以就发送字符A,再查询一遍,可以的话再发送字符B,再查询一遍,可以的话就发送回车换行。
之后一直循环,首先将PA8置位,因为PA8连接到了蜂鸣器上,所以程序运行时会有“嗒嗒”的响声,之后启动延时程序,其程序定义如下:

显而易见,延时程序的实现主要依赖循环来占用CPU,从而消耗时间。
之后将PA8清零,再次启动延时程序,之后轮询,打印“青岛大学物联网工程系欢迎您!”。
基本上打印出来是这个效果:
AB
青岛大学物联网工程系欢迎您!
青岛大学物联网工程系欢迎您!
青岛大学物联网工程系欢迎您!
青岛大学物联网工程系欢迎您!
青岛大学物联网工程系欢迎您!
……
……
……

你可能感兴趣的:(嵌入式系统原理及应用,嵌入式之USART)