STM32基础设计(2)---查询串口通信

点亮LED灯后,基本了解了GPIO口的使用,下面学通过查询方式运用USART1口收发数据。

首先总结全文,通过查询方式运用USART1口收发数据的主要步骤如下:

  1. 初始化GPIO口
  2. 初始化串口
  3. 编写发送数据函数
  4. 编写主函数

下面介绍详细步骤:

1.初始化GPIO口

通过查阅STM32数据手册可知,stm32f103c8 ,USART1的输入、输出引脚,分别为GPIOA端口的 Pin_10,Pin_9引脚,所以先定义GPIO结构体并赋值:

void IO_Init()
{
	GPIO_InitTypeDef Uart_A;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	Uart_A.GPIO_Pin = GPIO_Pin_9;
	Uart_A.GPIO_Speed = GPIO_Speed_50MHz;
	Uart_A.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_Init(GPIOA,&Uart_A);
	
	Uart_A.GPIO_Pin = GPIO_Pin_10;
	Uart_A.GPIO_Speed = GPIO_Speed_50MHz;
	Uart_A.GPIO_Mode = GPIO_Mode_IN_FLOATING; //stm32 data sheet page 110
	GPIO_Init(GPIOA,&Uart_A);

}

还和以前一样,先定义GPIO结构体变量,在使能GPIO外设时钟,紧接着分别对各个引脚的寄存器赋值并初始化。

这里需要注意引脚模式的选择:根据STM32参考手册,在全双工模式下,输出口的引脚(Pin_9)要配置为推挽复用输出,接收口的引脚(Pin_10)要配置为浮空输入或带上拉输入,刚开始学STM32不需要过深了解,只需要知道引脚要配置为相应模式即可。如想深究请查看STM32参考手册110页。

2,初始化串口

要初始化串口可以利用库函数中的串口结构体 USART_InitTypeDef,这样对于初学者来说方便易懂。

库函数中的结构体 USART_InitTypeDef为:

typedef struct
{//波特率
  uint32_t USART_BaudRate;            /*!< This member configures the USART communication baud rate.
                                           The baud rate is computed using the following formula:
                                            - IntegerDivider = ((PCLKx) / (16 * (USART_InitStruct->USART_BaudRate)))
                                            - FractionalDivider = ((IntegerDivider - ((u32) IntegerDivider)) * 16) + 0.5 */
//字长
  uint16_t USART_WordLength;          /*!< Specifies the number of data bits transmitted or received in a frame.
                                           This parameter can be a value of @ref USART_Word_Length */
//停止位
  uint16_t USART_StopBits;            /*!< Specifies the number of stop bits transmitted.
                                           This parameter can be a value of @ref USART_Stop_Bits */
//是否奇偶校验
  uint16_t USART_Parity;              /*!< Specifies the parity mode.
                                           This parameter can be a value of @ref USART_Parity
                                           @note When parity is enabled, the computed parity is inserted
                                                 at the MSB position of the transmitted data (9th bit when
                                                 the word length is set to 9 data bits; 8th bit when the
                                                 word length is set to 8 data bits). */
 //串口模式,收or发?
  uint16_t USART_Mode;                /*!< Specifies wether the Receive or Transmit mode is enabled or disabled.
                                           This parameter can be a value of @ref USART_Mode */
//是否使能硬件流,这个初学者暂时先放放,还用不到(博主现在是初学者)
  uint16_t USART_HardwareFlowControl; /*!< Specifies wether the hardware flow control mode is enabled
                                           or disabled.
                                           This parameter can be a value of @ref USART_Hardware_Flow_Control */
} USART_InitTypeDef;
知道了结构体,便可轻松理解下面的定义了。
USART_InitTypeDef Uart;

使能串口时钟后,依次对结构体中的变量赋值(注:STM32的每个外设都有其单独的时钟,只有使能了其时钟,外设才能开始工作)详细代码如下:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
Uart.USART_BaudRate = 115200;//波特率115200
Uart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//硬件流失能
Uart.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//设置为 输出和输入模式
Uart.USART_Parity = USART_Parity_No;//不进行奇偶校验
Uart.USART_StopBits = USART_StopBits_1;//1个停止位
Uart.USART_WordLength = USART_WordLength_8b;//单次数据长读为8
USART_Init(USART1,&Uart);//初始化串口

在初始化串口后,按照STM32参考手册还需要对usart使能见下图:


(注:博主当时在这里想到一个问题:STM32有多个串口,但是只有这一个串口使能位,也就是这么多串口公用一个使能位,那么,当使用多个串口工作,如果临时需要关闭一个串口,怎么办?答案见文章最下部分,答案1。)

由上图可知,在初始化串口完毕后,还需要使能串口:

USART_Cmd(USART1,ENABLE);

然后根据参考手册:



此时还需要先清除状态寄存器USART_SR的发送完成(TC)位,要不然发送数据的第一个字节显示不出来。代码如下:

SART_ClearFlag(USART1,USART_FLAG_TC);

到此,串口的初始化也就完成了。

3,编写发送函数

此处比较简单,先说代码:

void sendByte(uchar character)
{
	USART1->DR = character;
	while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);
}

需要发送时,直接把数据赋值给USART1的数据寄存器(USART_DR),即可通过串口发出,接下来需要等待数据发送完毕,当数据发送完毕后,USART的状态寄存器的发送寄存器空(TXE)位会置1,(RESET在库函数的宏定义为 0),即,若数据未发送完成,那么循环会一直空转,直到数据全部转到移位寄存器。


4.编写主函数

本文是通过运用查询方法来实现串口的发送。通过串口向电脑发送一个字符,串口之后会自动向电脑发送已发送字符的后9个。

先粘贴代码在解释:

int main()
{
	int count= -1;
	char temp= '0';
	IO_Init();
	Usart1_Init();
	while(1){
		if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE))//判断是否接受到数据
		{
			temp = USART1->DR;//若接收到数据,则将数据从数据寄存器取出
			count = 10;
		}	
		if(USART_GetFlagStatus(USART1,USART_FLAG_TC) && (count >=0))//判断能否发送数据
		{
			while(count >0){
			    sendByte(temp++);//若能发送数据,则向接收端发送数据
			    count--;//连着发送10个字符
			    delay(1000);延时一秒
			}
			if(count<0){
				sendByte('\r');//博主本来想在电脑接收端输出回车换行,但是一直接收不了,还没弄明白。
			}
		}
	}
}

解释见代码中的注释。

答案1:当不需要使用多个串口中的一个时,直接将对应串口外设的时钟失能就可以了。

通过查询方式实现串口收发数据完结。2018年3月20日

下一篇,通过中断来使用串口。

见STM32基础设计(3)---中断串口通信

本文的完整代码如下:

#include<stm32f10x.h>
#define uint unsigned int
#define uchar unsigned char
void delay(uint n)
{
	int i,j;
	for(i=0;i<n;i++)
	for(j=0;j<8500;j++);
}

void IO_Init()
{
	GPIO_InitTypeDef Uart_A;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	Uart_A.GPIO_Pin = GPIO_Pin_9;
	Uart_A.GPIO_Speed = GPIO_Speed_50MHz;
	Uart_A.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_Init(GPIOA,&Uart_A);
	
	Uart_A.GPIO_Pin = GPIO_Pin_10;
	Uart_A.GPIO_Speed = GPIO_Speed_50MHz;
	Uart_A.GPIO_Mode = GPIO_Mode_IN_FLOATING; //page 110
	GPIO_Init(GPIOA,&Uart_A);

}
void Usart1_Init()
{
	USART_InitTypeDef Uart;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	Uart.USART_BaudRate = 115200;
	Uart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	Uart.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	Uart.USART_Parity = USART_Parity_No;
	Uart.USART_StopBits = USART_StopBits_1;
	Uart.USART_WordLength = USART_WordLength_8b;
	USART_Init(USART1,&Uart);
	
	USART_Cmd(USART1,ENABLE);
	USART_ClearFlag(USART1,USART_FLAG_TC); //page 540
}

void sendByte(uchar character)
{
	USART1->DR = character;
	while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);
}

int main()
{
	int count= -1;
	char temp= '0';
	IO_Init();
	Usart1_Init();
	while(1){
		if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE))
		{
			temp = USART1->DR;
			count = 10;
		}	
		if(USART_GetFlagStatus(USART1,USART_FLAG_TC) && (count >=0))
		{
			while(count >0){
			    sendByte(temp++);
			    count--;
			    delay(1000);
			}
			if(count<0){
			    sendByte('\r');			   		
			}
		}
	}
}

猜你喜欢

转载自blog.csdn.net/aa867734398/article/details/79619156