STM32串口通信之Hello(STM32_11)

一、开发板硬件介绍

1、MCU串口管脚

    本程序使用STM32F103ZET6芯片,芯片有5个串口,其中有3个USART和两个UART,本程序使用异步方式,5个串口的管脚如下表所示。

STM32F103ZET6芯片的5个串口外设管脚

引脚

APB2总线

APB1总线

USART1

USART2

USART3

UART4

UART5

TX

PA9

PA2

PB10

PC10

PC12

RX

PA10

PA3

PB11

PC11

PD2

SCLK

PA8

PA4

PB12

 

 

nCTS

PA11

PA0

PB13

 

 

nRTS

PA12

PA1

PB14

 

 

2、卡发板串口电路

① USART1的电路连接

    开发板中将USART1的TX(USART1_TXD, PA9)和RX(USART1_RXD, PA10)连接至CH340G (USB转串口芯片)的TXD和RXD,在TXD引脚串联一个二极管是为了防止CH340G给单片机供电而使单片机不能正常断电,从而导致程序下载失败。DTR连RSET可以实现程序下载完成后自动复位系统。下载程序时通过RTS将BOOT0拉低。

② USART3的电路连接

需要使用直通线与PC端RS232串口连接

二、使用库函数的串口程序项目配置

1、新建项目文件夹"pUartHello";

2、在"pUartHello"文件夹中创建"CMSIS","Device","Lib","Startup"和"User"子文件夹,在"User"文件夹下新建"Uart"子文件夹;

3、向上述新建文件夹中复制必要文件。

① 向"CMSIS"文件夹中复制"core_cm3.c"和"core_cm3.h"文件;

② 向"Device"文件夹复制"stm32f10x.h"、"system_stm32f10x.c"、"system_stm32f10x.h"、"stm32f10x_conf.h"、" stm32f10x_it.c"和" stm32f10x_it.h "文件;

③ 向"Startup"文件夹下复制"startup_stm32f10x_hd.s"文件;

④ 向"Lib"文件夹下复制3.5版固件库函数的"inc"和"src"文件夹;

4、在Keil5中新建项目pUartHello,存放在"pUartHello"文件夹中;

5、点击按钮或者通过菜单"Project"->"Manage"->"Components,Environment,Books…"打开进行"Manage Project Items"对话框,对项目文件管理。在"Groups"中分别添加"CMSIS"、"Device"、"Startup"、"Lib"和"User"5个组,并为每一个组添加上述3中叙述的程序文件(.c和.s的文件)。

6、点击工具按钮,在对话框的"Output"选项卡中选中"Create HEX File",在"C/C++"选项卡中的"Include Paths"项目点击按钮,打开"Folder Setup"对话框,添加如下包含路径:".\CMSIS",".\Lib\inc",".\Device",".\User\Uart";在"C/C++"选项卡中的"Preprocessor Symbols"中的"Define"中输入"USE_STDPERIPH_DRIVER",表示使用标准外设驱动库(在"stm32f10x.h"文件中有

#ifdef USE_STDPERIPH_DRIVER

  #include "stm32f10x_conf.h"

#endif

如果定义了该标示,则包含"stm32f10x_conf.h"头文件,在"stm32f10x_conf.h"头文件中可以选择需要包含的库函数头文件)。

7、新建"main.c"文件保存在".\User"文件夹下,内容为:

#include "stm32f10x.h"

int main()

{

         return 0;

}

并将"main.c"文件添加到“项目文件管理”的"User"组中,此时可以编译生成".Hex"文件。

三、使用库函数的串口程序设计

1、在"stm32f10x_conf.h"头文件中包含本程序需要的GPIO、RCC和USART三个头文件,将其它头文件包含注释掉:

#include "stm32f10x_gpio.h"

#include "stm32f10x_rcc.h"

#include "stm32f10x_usart.h"

2、新建"Uart.h"头文件,保存在".\User\Uart"文件夹下,内容为:

#ifndef __UART__H

#define __UART__H

#include "stm32f10x.h"

void USART1_Config(void);

#endif

3、新建"Uart.c"程序文件,保存在".\User\Uart"文件夹下,内容为:

#include "uart.h"

void USART1_Config(void)

{

         GPIO_InitTypeDef GPIO_InitStructure;

         USART_InitTypeDef USART_InitStructure;

         //Enable GPIOA and USART1

         RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);

         //Config GPIOA_9 and GPIOA_10

         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;

         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

         GPIO_Init(GPIOA, &GPIO_InitStructure);

        

         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;

         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

         GPIO_Init(GPIOA, &GPIO_InitStructure);

         //Config USART1

         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_Rx | USART_Mode_Tx;

         USART_Init(USART1, &USART_InitStructure);

         //Enable USART1

         USART_Cmd(USART1, ENABLE);

}

3、修改"main.c"文件,内容为:

#include "uart.h"

int main()

{

         u8 i;

         u8 s[] = "Hello\r\n";

         USART1_Config();

         while(1)

         {

                   for(i=0; i<sizeof(s)/sizeof(s[0]); i++)

                            USART_SendData(USART1, s[i]);

         }

}

以上程序中,首先调用USART1_Config函数使能GPIOA和USART1的时钟、配置GPIOA_9和GPIOA_10管脚、配置UASRT1的工作模式为“波特率115200,8个数据位,一个停止位,无校验,无硬件流控制”、打开USART1,然后调用库函数USART_SendData实现数据发送,不断发送"Hello\r\n"。

PC端通过串口助手收到信息如下:

在上述串口通信程序中,从PC端的串口调试助手收到的信息并不是完整的"Hello"信息,而是比较杂乱的,原因是在STM32中程序运行速度是比较快的,交给串口USART1发送一个字符后,USART1还没有发送完成,程序又向它传了下一个字符,这时这个字符会丢弃掉,这样,接收方就收不到完整信息,所以,需要在通过USART_SendData函数发送一个数据后,再通过USART_GetFlagStatus函数检查数据发送是否完成。

函数USART_SendData的原形为:

FlagStatus USART_GetFlagStatus(USART_TypeDef*USARTx, u16 USART_FLAG);

其中USART_FLAG可以取的值为:

USART_FLAG

描述

USART_FLAG_CTS

CTS标志位

USART_FLAG_LBD

LIN中断检测标志位

USART_FLAG_TXE

发送数据寄存器空标志位

USART_FLAG_TC

发送完成标志位

USART_FLAG_RXNE

接收数据寄存器非空标志位

USART_FLAG_IDLE

空闲总线标志位

USART_FLAG_ORE

溢出错误标志位

USART_FLAG_NE

噪声错误标志位

USART_FLAG_FE

帧错误标志位

USART_FLAG_PE

奇偶错误标志位

该函数的返回值可以为"SET"或"RESET"。

这里将修改"main.c"文件,改为:

#include "uart.h"

int main()

{

         u8 i;

         u8 s[] = "Hello\r\n";

         USART1_Config();

         while(1)

         {

                   for(i=0; i<sizeof(s)/sizeof(s[0]); i++)

                   {

                            USART_SendData(USART1, s[i]);

                            while( USART_GetFlagStatus(USART1, USART_FLAG_TC) != SET );

                   }

         }

}

调整后的结果为:

四、使用USART3发送数据

1、在"uart.h"头文件中增加"USART3_Config"函数的声明:

void USART3_Config(void);

2、在"uart.c"程序文件中增加"USART3_Config"函数的定义:

void USART3_Config(void)

{

         GPIO_InitTypeDef GPIO_InitStructure;

         USART_InitTypeDef USART_InitStructure;

         //Enable GPIOB and USART3

         RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);

         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

         //Config GPIOB_10 and GPIOB_11

         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;

         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

         GPIO_Init(GPIOB, &GPIO_InitStructure);

        

         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;

         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

         GPIO_Init(GPIOB, &GPIO_InitStructure);

         //Config USART3

         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_Rx | USART_Mode_Tx;

         USART_Init(USART3, &USART_InitStructure);

         //Enable USART3

         USART_Cmd(USART3, ENABLE);

}

由于USART3在APB1上,所以使用RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);来使能USART3的时钟,USART3的数据发送和数据接收使用PB10和PB11,所以需要对GPIOB使能时钟,使用RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);实现。其他与USART1类似。

在"main.c"中使用如下:

#include "uart.h"

int main()

{

         u8 i;

         u8 s[] = "Hello\r\n";

         USART3_Config();

         while(1)

         {

                   for(i=0; i<sizeof(s)/sizeof(s[0]); i++)

                   {

                            USART_SendData(USART3, s[i]);

                            while( USART_GetFlagStatus(USART3, USART_FLAG_TC) != SET );

                   }

         }

}

注意,使用开发板的USART3首先要将P232跳线帽接到COM3,然后通过直连RS232串口线与电脑COM口相连。


猜你喜欢

转载自blog.csdn.net/fanxp66/article/details/80509189