stm32f10x串口通信的写法
Posted 旭日初扬
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了stm32f10x串口通信的写法相关的知识,希望对你有一定的参考价值。
目录
一、串口配置
1.1、数据类型重新定义及调试用的宏
/***********************无符号类型的定义****************************/
typedef unsigned char st_u8;
typedef unsigned short int st_u16;
typedef unsigned int st_u32;
//typedef unsigned __INT64 st_u64;
/***********************有符号类型的定义****************************/
typedef signed char st_8;
typedef signed short int st_16;
typedef signed int st_32;
/***********************其他数据类型定义方式****************************/
#define uint8 unsigned char
#define uint16 unsigned short int
#define uint32 unsigned long int
#define int8 signed char
#define int16 signed short int
#define int32 signed long int
#define uint64 unsigned long long int
#define int64 signed long long int
//typedef signed __INT64 st_64
/*********************************************全局变量条件编译***************************************/
#ifdef ROOT
#define EXT
#define ext
#else
#define EXT extern
#define ext extern
#endif
/*********************************************位定义*********************************************/
typedef enum
FALSE = 0,
TRUE = !FALSE
boot;
/*********************************************调试宏*****************************************/
#define DEBUG_USART_PRINTF 1 // printf 使能
#define USART1_ENABLE 1
#define USART2_ENABLE 1
#define USART3_ENABLE 1
1.2、端口封装
// GPIO时钟 宏定义
#define GPIOx_RCC_APB2Periph RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC \\
RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOE|RCC_APB2Periph_GPIOF \\
RCC_APB2Periph_GPIOG
void GPIOx_config(st_u32 GPIOx_RCC,GPIO_TypeDef *GPIOxPORT,st_u16 GPIOPin,GPIOMode_TypeDef GPIOMode)
RCC_APB2PeriphClockCmd(GPIOx_RCC, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
/* Configure PD0 and PD2 in output pushpull mode */
GPIO_InitStructure.GPIO_Pin =GPIOPin;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIOMode;
GPIO_Init(GPIOxPORT, &GPIO_InitStructure);
st_u8 GPioset(GPIO_TypeDef* GPIOx, uint16_t GPIOPin, uint16_t GPIOMode)
if(GPIOMode == 0)
//USART3->DR
GPIO_ResetBits(GPIOx,GPIOPin);
else
GPIO_SetBits(GPIOx,GPIOPin);
return GPIOMode;
// uint8_t GPIOGet(GPIO_TypeDef* GPIOx, uint16_t GPIOPin)
st_u8 GPIOGet(GPIO_TypeDef* GPIOx, uint16_t GPIOPin)
return (GPIO_ReadInputDataBit(GPIOx, GPIOPin));
1.3、串口通信逻辑代码
static void Uart1_Config(void);
/*********************************************USART1*****************************************/
#if USART1_RX_EN
void Uart1_Config(void)
NVIC_Config(USART1_IRQn, 2, 1);
GPIOx_config(GPIOx_CLK, USART1_PORT, USART1_TX_PIN, GPIO_Mode_AF_PP); // TX PA9 复用推挽输出
GPIOx_config(GPIOx_CLK, USART1_PORT, USART1_RX_PIN, GPIO_Mode_IN_FLOATING); // RX PA10 浮空输入
USART_Config(115200, USART1);
void UART1Init(void)
USART_RX_STA = 0;
Uart1_Config();
void USART1_Int(void)
// INTX_DISABLE();
st_u8 r; //temp;
// 是否发生接收中断 1发生 0 没有发生
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断
r = USART_ReceiveData(USART1); //(USART1->DR); //读取接收到的数据
if ((USART_RX_STA & 0x8000) == 0) //接收未完成
if (USART_RX_STA & 0x4000) //接收到了0x0d
if (r != 0x0a) USART_RX_STA = 0; //接收错误,重新开始
else USART_RX_STA |= 0x8000; //接收完成了
else //还没收到0X0D
if (r == 0x0d) USART_RX_STA |= 0x4000;
else
USART_RX_BUF[USART_RX_STA & 0X3FFF] = r;
USART_RX_STA++;
if (USART_RX_STA > (USART_REC_LEN - 1)) USART_RX_STA = 0; //接收数据错误,重新开始接收
#endif
/*********************************************测试PRINTF*********************************************/
/*********************************************USART2*****************************************/
void UART1_Test(void)
printf("提示信息:%s\\r\\n", "USART1测试");
#ifndef _USART_H
#define _USART_H
/*********************************************USART1*****************************************/
#define USART1_RCC RCC_APB2Periph_USART1 // 串口时钟
#define USART1_PORT GPIOA // 端口
#define GPIOx_CLK RCC_APB2Periph_GPIOA // 端口时钟
#define USART1_TX_PIN GPIO_Pin_9 // USART1_TX
#define USART1_RX_PIN GPIO_Pin_10 // USART1_RX
#define USART1_RX_EN 1 // uSART1使能位
#define USART_REC_LEN 200 // 接受数组
#define USART_SEC_LEN 200 // 发送数组
// bit0~13 接收有效数据的长度
// bit14 接收0xOD 回车的表示由 2 个字节组成:0X0D 和 0X0A
// bit15 接收完成的标记
ext st_u16 USART_RX_STA;
ext st_u8 USART_RX_BUF[USART_REC_LEN];
extern void UART1Init(void);
extern void UART1_Test(void);
extern void USART1_Int(void);
/*********************************************USART2*****************************************/
#endif
1.4、中断服务函数
写在stm32f10x_it.c文件中
void USART1_IRQHandler(void)
USART1_Int();
1.5、支持printf
/*********************************************串口printf函数的使用*********************************************/
#if DEBUG_USART_PRINTF
#pragma import (__use_no_semihosting) // 确保没有从 C 库链接使用半主机的函数
// 标准库需要的支持函数
struct __FILE int handle;;
FILE __stdout;
void _sys_exit(int x) x = x; // 定义 _sys_exit() 以避免使用半主机模式
// 重定义fputc函数
int fputc(int ch, FILE * f)
#if 0
while ((USART1 - > SR & 0X40) == 0) // 循环发送,直到发送完毕
USART1 - > DR = (u8) ch;
return ch;
#else
if(USART2_ENABLE==1)
USART_SendData(USART2, (st_u8) ch);
//while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET)
while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET); // USART_FLAG_TXE 数据寄存器为空的标记
else if(USART1_ENABLE==1)
USART_SendData(USART1, (st_u8) ch);
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); // USART_FLAG_TXE 数据寄存器为空的标记
else if(USART3_ENABLE==1)
USART_SendData(USART3, (st_u8) ch);
while (USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET); // USART_FLAG_TXE 数据寄存器为空的标记
return ch;
#endif
// 接收数据
// 重定向 c 库函数 scanf 到串口,重写向后可使用 scanf、getchar 等函数
int fgetc(FILE * f)
static st_u32 TempData;
if(USART2_ENABLE==1)
while(USART_GetFlagStatus(USART2, USART_IT_RXNE) == RESET)
TempData=USART_ReceiveData(USART2);
// return (st_32) USART_ReceiveData(USART2);
else if(USART1_ENABLE==1)
while (USART_GetFlagStatus(USART1, USART_IT_RXNE) == RESET)
TempData= USART_ReceiveData(USART1);
else if(USART3_ENABLE==1)
while (USART_GetFlagStatus(USART3, USART_IT_RXNE) == RESET)
TempData= USART_ReceiveData(USART3);
return TempData;
/*********************************************向串口发送一个字符/字节*********************************************/
void Usart_SendByte(USART_TypeDef * pUSARTx, st_u8 ch)
USART_SendData(pUSARTx, ch);
while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
/*********************************************向串口发送字符串*********************************************/
void Usart_SendString(USART_TypeDef * pUSARTx, char * str)
st_u32 k = 0;
do
Usart_SendByte(pUSARTx, * (str + k));
k++;
while ( * (str + k) != '\\0');
while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TC) == RESET); // 等待发送完成
#endif
/*********************************************获取一个数据的字节长度(最大255)*********************************************/
st_u8 ByteLen(st_u8 *p) // 字符长度
st_u8 Count = 0;
// 获取Bye数目,#define SEC_BYTESIZE_MAX 200
for(st_u8 i=0;i<200;i++)
// 指针指向'0'地址结束结束计数
if((*(p+i))!= '\\0')
Count++;
else
break;
return Count;
/*********************************************获取一个数据的字节长度(16位,最大65535)*********************************************/
st_u8 ByteLen_16(st_u16 *p) // 字符长度
st_u8 Count = 0;
// 获取Bye数目,#define SEC_BYTESIZE_MAX 200
for(st_u8 i=0;i<200;i++)
// 指针指向'0'地址结束结束计数
if((*(p+i))!= '\\0')
Count++;
else
break;
return Count;
/*********************************************获取一个数据的字节长度(32位)*********************************************/
st_u8 ByteLen_32(st_u32 *p) // 字符长度
st_u8 Count = 0;
// 获取Bye数目,#define SEC_BYTESIZE_MAX 200
for(st_u8 i=0;i<200;i++)
// 指针指向'0'地址结束结束计数
if((*(p+i))!= '\\0')
Count++;
else
break;
return Count;
/*********************************************将指定个数的字符串从一个地方拷贝到另外一个地方*********************************************/
st_u8 *rt_strncpy(st_u8 *dst, const st_u8 *src, st_u32 n)
if (n != 0)
st_u8 *d = dst;
const st_u8 *s = src;
do
if ((*d++ = *s++) == 0)
/* NUL pad the remaining n-1 bytes */
while (--n != 0)
*d++ = 0;
break;
while (--n != 0);
return (dst);
1.6、中断及串口的封装
/********************************************* 中断优先级配置*********************************************/
// 中断分组配置 NVIC_PriorityGroupConfig
void NVIC_PG_Config(st_u32 PG)
/*
中断分组号 抢占式优先级 子优先级配置/响应式优先级 分配位数
0 0 0-15 抢0bit 响4bit(1111)
1 0~1 0~7 抢1bit 响3bit(0111)
2 0~3 0~3 抢2bit 响2bit(0011)
3 0~7 0~1 抢3bit 响1bit(0001)
4 0~15 0 抢4bit 响0bit(0000)
特征:在抢占式优先级相同的情况下,高响应优先级的中断优先被响应。
抢占式优先级数值越小,优先级越高
*/
if(PG==NVIC_PriorityGroup_0)
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
else if(PG==NVIC_PriorityGroup_1)
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
else if(PG==NVIC_PriorityGroup_2)
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
else if(PG==NVIC_PriorityGroup_3)
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);
else if(PG==NVIC_PriorityGroup_4)
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
else
printf("%s","没有使用中断分组\\r\\n");
// 中断优先级配置
void NVIC_Config(st_u8 IRQn,st_u8 IRQChannelPriority,st_u8 IRQChannelSubPriority)
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =IRQChannelPriority; // 抢占式优先级 0~15
NVIC_InitStructure.NVIC_IRQChannelSubPriority =IRQChannelSubPriority ; // 子优先级 0~15
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 外部中断配置
void EXTI_Config(void)
// 外部中断初始化
/*********************************************串口配置*********************************************/
void USART_Config(st_u32 BaudRate,USART_TypeDef* USARTx)
USART_InitTypeDef USART_InitStructure;
if(USARTx==USART1)RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
if(USARTx==USART2)RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
/* USART1工作模式配置 */
USART_InitStructure.USART_BaudRate = BaudRate; //波特率设置:
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //数据位数设置:8位
USART_InitStructure.USART_StopBits = USART_StopBits_1; //停止位设置: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(USARTx, &USART_InitStructure); //初始化USART1
// 使能串口接收中断
USART_ITConfig(USARTx, USART_IT_RXNE, ENABLE);
// 使能中断发送
USART_ITConfig(USARTx, USART_IT_TXE, ENABLE);
USART_Cmd(USARTx, ENABLE); // USART使能
以上是关于stm32f10x串口通信的写法的主要内容,如果未能解决你的问题,请参考以下文章