首先总结全文,通过查询方式运用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;
复制代码
知道了结构体,便可轻松理解下面的定义了。
使能串口时钟后,依次对结构体中的变量赋值(注: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');
- }
- }
- }
- }
复制代码
————————————————
版权声明:家安
|