本篇博文最后修改时间:2016年12月28日,11:59。
一、简介
本文介绍如何使用STM32的串口,串口1和串口2的驱动都写好了,本文以串口2的驱动为例。
二、实验平台
库版本:STM32F10x_StdPeriph_Lib_V3.5.0
编译软件:MDK4.53
硬件平台:STM32开发板(主芯片stm32f103c8t6)
仿真器:JLINK
三、版权声明
博主:甜甜的大香瓜
声明:喝水不忘挖井人,转载请注明出处。
原文地址:http://blog.csdn.NET/feilusia
联系方式:897503845@qq.com
香瓜BLE之CC2541群:127442605
香瓜BLE之CC2640群:557278427
香瓜单片机之STM8/STM32群:164311667
甜甜的大香瓜的小店(淘宝店):https://shop217632629.taobao.com/?spm=2013.1.1000126.d21.hd2o8i
四、实验前提
在进行本文步骤前,请先阅读并实现以下博文:
1、《STM32之NVIC》:http://blog.csdn.net/feilusia/article/details/52819709
五、实验步骤
1、编写并添加串口驱动
1)编写驱动GUA_USART.c(存放在“……\HARDWARE”)
//******************************************************************************
//name: GUA_USART.c
//introduce: 串口驱动
//author: 甜甜的大香瓜
//email: 897503845@qq.com
//QQ group 香瓜单片机之STM8/STM32(164311667)
//changetime: 2016.12.28
//******************************************************************************
#include "stm32f10x.h"
#include "GUA_USART.h"
/*********************宏定义************************/
#define GUA_USART_TIMEOUT ((GUA_U32)0xFFF) //串口超时时间
/*********************全局变量************************/
//串口1缓冲区
GUA_U8 gGUA_USART1_rx_buf[GUA_USART1_RX_SIZE] = {0};
GUA_U8 gGUA_USART1_tx_buf[GUA_USART1_TX_SIZE] = {0};
//串口2缓冲区
GUA_U8 gGUA_USART2_rx_buf[GUA_USART2_RX_SIZE] = {0};
GUA_U8 gGUA_USART2_tx_buf[GUA_USART2_TX_SIZE] = {0};
/*********************内部函数声明************************/
static void GUA_USART1_Init(GUA_U32 nGUA_BaudRate, GUA_U32 nGUA_WordLength, GUA_U32 nGUA_StopBits,
GUA_U32 nGUA_Parity, FunctionalState GUA_IT_Tx_NewState,
FunctionalState GUA_IT_Rx_NewState, FunctionalState GUA_Cmd_NewState);
static void GUA_USART2_Init(GUA_U32 nGUA_BaudRate, GUA_U32 nGUA_WordLength, GUA_U32 nGUA_StopBits,
GUA_U32 nGUA_Parity, FunctionalState GUA_IT_Tx_NewState,
FunctionalState GUA_IT_Rx_NewState, FunctionalState GUA_Cmd_NewState);
//******************************************************************************
//name: GUA_USART1_Init
//introduce: USART1初始化
//parameter: nGUA_BaudRate:波特率, nGUA_WordLength:数据长度, nGUA_StopBits:停止位
// nGUA_Parity:校验位, GUA_IT_Tx_NewState:发送中断使能位, GUA_IT_Rx_NewState:接收中断使能位,
// GUA_Cmd_NewState:串口使能位
//return: none
//author: 甜甜的大香瓜
//email: 897503845@qq.com
//QQ group 香瓜单片机之STM8/STM32(164311667)
//changetime: 2016.12.28
//******************************************************************************
static void GUA_USART1_Init(GUA_U32 nGUA_BaudRate, GUA_U32 nGUA_WordLength, GUA_U32 nGUA_StopBits,
GUA_U32 nGUA_Parity, FunctionalState GUA_IT_Tx_NewState,
FunctionalState GUA_IT_Rx_NewState, FunctionalState GUA_Cmd_NewState)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
USART_ClockInitTypeDef USART_ClockInitStructure;
//开GPIOA、AFIO、USART1时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO | RCC_APB2Periph_USART1, ENABLE);
//复位
USART_DeInit(USART1);
//IO配置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA,&GPIO_InitStructure);
//时序配置
USART_ClockInitStructure.USART_Clock = USART_Clock_Disable;
USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;
USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge;
USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable;
USART_ClockInit(USART1,&USART_ClockInitStructure);
//串口配置
USART_InitStructure.USART_BaudRate = nGUA_BaudRate; //设置串口通信时的波特率
USART_InitStructure.USART_WordLength = nGUA_WordLength; //设置数据位的长度
USART_InitStructure.USART_StopBits = nGUA_StopBits; //设置停止位
USART_InitStructure.USART_Parity = nGUA_Parity ; //设置校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //设置硬件控制流失能
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //设置发送使能,接收使能
USART_Init(USART1, &USART_InitStructure); //将以上赋完值的结构体带入库函数USART_Init进行初始化
USART_ITConfig(USART1, USART_IT_TXE, GUA_IT_Tx_NewState); //串口1发送中断
USART_ITConfig(USART1, USART_IT_RXNE, GUA_IT_Rx_NewState); //串口1接收中断
USART_Cmd(USART1, GUA_Cmd_NewState); //使能USART1
USART_ClearFlag(USART1, USART_FLAG_TC); //清除发送标志
USART_ClearFlag(USART1, USART_FLAG_RXNE); //清除接收标志
}
//******************************************************************************
//name: GUA_USART2_Init
//introduce: USART2初始化
//parameter: nGUA_BaudRate:波特率, nGUA_WordLength:数据长度, nGUA_StopBits:停止位
// nGUA_Parity:校验位, GUA_IT_Tx_NewState:发送中断使能位, GUA_IT_Rx_NewState:接收中断使能位,
// GUA_Cmd_NewState:串口使能位
//return: none
//author: 甜甜的大香瓜
//email: 897503845@qq.com
//QQ group 香瓜单片机之STM8/STM32(164311667)
//changetime: 2016.12.28
//******************************************************************************
static void GUA_USART2_Init(GUA_U32 nGUA_BaudRate, GUA_U32 nGUA_WordLength, GUA_U32 nGUA_StopBits,
GUA_U32 nGUA_Parity, FunctionalState GUA_IT_Tx_NewState,
FunctionalState GUA_IT_Rx_NewState, FunctionalState GUA_Cmd_NewState)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
USART_ClockInitTypeDef USART_ClockInitStructure;
//开GPIOA、AFIO、USART2时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
//复位
USART_DeInit(USART2);
//IO配置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA,&GPIO_InitStructure);
//时序配置
USART_ClockInitStructure.USART_Clock = USART_Clock_Disable;
USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;
USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge;
USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable;
USART_ClockInit(USART2,&USART_ClockInitStructure);
//串口配置
USART_InitStructure.USART_BaudRate = nGUA_BaudRate; //设置串口通信时的波特率
USART_InitStructure.USART_WordLength = nGUA_WordLength; //设置数据位的长度
USART_InitStructure.USART_StopBits = nGUA_StopBits; //设置停止位
USART_InitStructure.USART_Parity = nGUA_Parity ; //设置校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //设置硬件控制流失能
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //设置发送使能,接收使能
USART_Init(USART2, &USART_InitStructure); //将以上赋完值的结构体带入库函数USART_Init进行初始化
USART_ITConfig(USART2, USART_IT_TXE, GUA_IT_Tx_NewState); //串口2发送中断
USART_ITConfig(USART2, USART_IT_RXNE, GUA_IT_Rx_NewState); //串口2接收中断
USART_Cmd(USART2, GUA_Cmd_NewState); //使能USART2
USART_ClearFlag(USART2, USART_FLAG_TC); //清除发送标志
USART_ClearFlag(USART2, USART_FLAG_RXNE); //清除接收标志
}
//******************************************************************************
//name: GUA_USARTx_Send
//introduce: 串口发送函数
//parameter: GUA_USARTx:USART1或USART2, pGUA_Data:数据发送缓冲区, nGUA_Len:数据长度
//return: none
//author: 甜甜的大香瓜
//email: 897503845@qq.com
//QQ group 香瓜单片机之STM8/STM32(164311667)
//changetime: 2016.12.28
//******************************************************************************
void GUA_USARTx_Send(USART_TypeDef* GUA_USARTx, GUA_U8 *pGUA_Data, GUA_U8 nGUA_Len)
{
GUA_U8 i = 0;
for(i = 0; i < nGUA_Len; i++)
{
while(USART_GetFlagStatus(GUA_USARTx, USART_FLAG_TC) != SET);
USART_SendData(GUA_USARTx, pGUA_Data[i]);
}
}
//******************************************************************************
//name: GUA_USARTx_Reveive
//introduce: 串口接收函数
//parameter: GUA_USARTx:USART1或USART2, pGUA_Data:数据接收缓冲区
//return: none
//author: 甜甜的大香瓜
//email: 897503845@qq.com
//QQ group 香瓜单片机之STM8/STM32(164311667)
//changetime: 2016.12.28
//******************************************************************************
GUA_U8 GUA_USARTx_Reveive(USART_TypeDef* GUA_USARTx, GUA_U8 *pGUA_Data)
{
GUA_U8 nGUA_Num = 0;
GUA_U32 nGUA_Timeout = 0;
GUA_U8 *pGUA_Data_Temp = pGUA_Data;
while(1)
{
//等待接收缓冲区收到数据
nGUA_Timeout= GUA_USART_TIMEOUT;
while(USART_GetITStatus(GUA_USARTx, USART_IT_RXNE) == RESET)
{
//等待超时则退出函数
if((nGUA_Timeout--) == 0)
return nGUA_Num;
}
//计算接收到的数据个数
nGUA_Num++;
//保存数据到临时缓冲区
*pGUA_Data_Temp++ = USART_ReceiveData(GUA_USARTx);
}
}
//******************************************************************************
//name: GUA_USART_Init
//introduce: 串口初始化
//parameter: none
//return: none
//author: 甜甜的大香瓜
//email: 897503845@qq.com
//QQ group 香瓜单片机之STM8/STM32(164311667)
//changetime: 2016.12.28
//******************************************************************************
void GUA_USART_Init(void)
{
//GUA_USART1_Init(9600,USART_WordLength_8b,USART_StopBits_1,USART_Parity_No,DISABLE, DISABLE, ENABLE);
GUA_USART2_Init(9600, USART_WordLength_8b, USART_StopBits_1, USART_Parity_No, DISABLE, ENABLE, ENABLE);
}
2)
编写驱动头文件
GUA_USART.h(存放在“
……
\HARDWARE
”)
//******************************************************************************
//name: GUA_USART.h
//introduce: 串口驱动的头文件
//author: 甜甜的大香瓜
//email: 897503845@qq.com
//QQ group 香瓜单片机之STM8/STM32(164311667)
//changetime: 2016.12.28
//******************************************************************************
#ifndef _GUA_USART_H_
#define _GUA_USART_H_
/*********************头文件************************/
#include "stm32f10x.h"
/*********************宏定义************************/
#ifndef GUA_U8
typedef unsigned char GUA_U8;
#endif
#ifndef GUA_8
typedef signed char GUA_8;
#endif
#ifndef GUA_U16
typedef unsigned short GUA_U16;
#endif
#ifndef GUA_16
typedef signed short GUA_16;
#endif
#ifndef GUA_U32
typedef unsigned long GUA_U32;
#endif
#ifndef GUA_32
typedef signed long GUA_32;
#endif
#ifndef GUA_U64
typedef unsigned long long GUA_U64;
#endif
#ifndef GUA_64
typedef signed long long GUA_64;
#endif
//串口1缓冲区大小
#define GUA_USART1_RX_SIZE 17
#define GUA_USART1_TX_SIZE 17
//串口2缓冲区大小
#define GUA_USART2_RX_SIZE 17
#define GUA_USART2_TX_SIZE 17
/*********************外部变量************************/
//串口1缓冲区
extern GUA_U8 gGUA_USART1_rx_buf[GUA_USART1_RX_SIZE];
extern GUA_U8 gGUA_USART1_tx_buf[GUA_USART1_TX_SIZE];
//串口2缓冲区
extern GUA_U8 gGUA_USART2_rx_buf[GUA_USART2_RX_SIZE];
extern GUA_U8 gGUA_USART2_tx_buf[GUA_USART2_TX_SIZE];
/*********************外部函数************************/
extern void GUA_USARTx_Send(USART_TypeDef* GUA_USARTx, GUA_U8 *pGUA_Data, GUA_U8 nGUA_Len);
extern GUA_U8 GUA_USARTx_Reveive(USART_TypeDef* GUA_USARTx, GUA_U8 *pGUA_Data);
extern void GUA_USART_Init(void);
#endif
4)在MDK设置中添加串口驱动源文件路径
2、添加库的驱动
1)添加库的驱动文件
2)添加库的驱动头文件(stm32f10x_conf.h 中)
#include "stm32f10x_usart.h"
3、设置NVIC中断优先级(GUA_NVIC.c的GUA_NVIC_Init中)
//串口中断
GUA_NVIC_Config(NVIC_PriorityGroup_2, USART2_IRQn, 0, 1, ENABLE);
4、写中断服务函数(stm32f10x_it.c中)
1)添加头文件
#include "GUA_USART.h"
2)写串口2中断服务函数
//******************************************************************************
//name: USART2_IRQHandler
//introduce: 串口2中断服务函数
//parameter: none
//return: none
//author: 甜甜的大香瓜
//email: 897503845@qq.com
//QQ group 香瓜单片机之STM8/STM32(164311667)
//changetime: 2016.10.17
//******************************************************************************
void USART2_IRQHandler(void)
{
//接收串口数据
nNum = GUA_USARTx_Reveive(USART2, gGUA_USART2_rx_buf);
//将接收到的数据发送出去
GUA_USARTx_Send(USART2, &gGUA_USART2_rx_buf, nNum);
}
5、在应用层中调用
1)添加驱动头文件(main.c中)
#include "GUA_USART.h"
2) 添加驱动初始化代码(main.c的main函数中)
//中断优先级配置
GUA_NVIC_Init();
//串口初始化
GUA_USART_Init();