GPIO-USART⚡️
文章目录
使用USART流程(例中使用串口1)🌘
方法一 printf 法📃
第一步 USART.h中设置
1️⃣:设置使用的串口,在头文件中将 #define USART_n USART1
中USART1的最后一个数改为要使用的串口号。
2️⃣:打开USART使能,打开需要使用的串口
#define EN_USART1 1 //使能(1)/禁止(0)串口1 #define EN_USART2 0 //使能(1)/禁止(0)串口2 #define EN_USART3 0 //使能(1)/禁止(0)串口3
USART.H事例:
#ifndef __USART_H
#define __USART_H
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "stdio.h"
#include "sys.h"
#define USART_n USART1 //定义使用printf函数的串口,其他串口要使用USART_printf专用函数发送
#define USART1_REC_LEN 200 //定义USART1最大接收字节数
#define USART2_REC_LEN 200 //定义USART2最大接收字节数
#define USART3_REC_LEN 200 //定义USART3最大接收字节数
//不使用某个串口时要禁止此串口,以减少编译量
#define EN_USART1 1 //使能(1)/禁止(0)串口1
#define EN_USART2 0 //使能(1)/禁止(0)串口2
#define EN_USART3 0 //使能(1)/禁止(0)串口3
extern u8 USART1_RX_BUF[USART1_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
extern u8 USART2_RX_BUF[USART2_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
extern u8 USART3_RX_BUF[USART3_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
extern u16 USART1_RX_STA; //接收状态标记
extern u16 USART2_RX_STA; //接收状态标记
extern u16 USART3_RX_STA; //接收状态标记
//函数声明
void USART1_Init(u32 bound);//串口1初始化并启动
void USART2_Init(u32 bound);//串口2初始化并启动
void USART3_Init(u32 bound);//串口3初始化并启动
void USART1_printf(char* fmt,...); //串口1的专用printf函数
void USART2_printf(char* fmt,...); //串口2的专用printf函数
void USART3_printf(char* fmt,...); //串口3的专用printf函数
#endif
第二步 main.c 中调用函数
1️⃣:在最上方包含usart的头文件
#include “usart.h”
2️⃣:在USART头文件选择需要的串口初始化函数,拷贝到main.c中,并设置波特率(例如9600)。
USART1_Init(9600);
3️⃣:接下来就可以自由自在的使用printf函数了😄
printf(“Hello World!”);
main.c事例
#include "stm32f10x.h"
#include "stm32f10x_conf.h"
#include "usart.h"
int main(void)
{
USART1_Init(9600);
USART1_printf("Hello World!");
while(1);
}
printf的好处
1 | 调用简单。 |
---|---|
2 | 发生数据方便。 |
3 | 对C语言学习者友好 |
printf的缺点
- 使用printf函数时只能由一个串口提供,也就是多个串口选择那一个用作printf,不能多个串口都使用printf函数
方法二 独立串口USART1_printf法📃
第一步 USART.h中设置
**打开USART使能,打开需要使用的串口 **
#define EN_USART1 1 //使能(1)/禁止(0)串口1 #define EN_USART2 0 //使能(1)/禁止(0)串口2 #define EN_USART3 0 //使能(1)/禁止(0)串口3
USART.H事例:
#ifndef __USART_H
#define __USART_H
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "stdio.h"
#include "sys.h"
#define USART_n USART1 //定义使用printf函数的串口,其他串口要使用USART_printf专用函数发送
#define USART1_REC_LEN 200 //定义USART1最大接收字节数
#define USART2_REC_LEN 200 //定义USART2最大接收字节数
#define USART3_REC_LEN 200 //定义USART3最大接收字节数
//不使用某个串口时要禁止此串口,以减少编译量
#define EN_USART1 1 //使能(1)/禁止(0)串口1
#define EN_USART2 0 //使能(1)/禁止(0)串口2
#define EN_USART3 0 //使能(1)/禁止(0)串口3
extern u8 USART1_RX_BUF[USART1_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
extern u8 USART2_RX_BUF[USART2_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
extern u8 USART3_RX_BUF[USART3_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
extern u16 USART1_RX_STA; //接收状态标记
extern u16 USART2_RX_STA; //接收状态标记
extern u16 USART3_RX_STA; //接收状态标记
//函数声明
void USART1_Init(u32 bound);//串口1初始化并启动
void USART2_Init(u32 bound);//串口2初始化并启动
void USART3_Init(u32 bound);//串口3初始化并启动
void USART1_printf(char* fmt,...); //串口1的专用printf函数
void USART2_printf(char* fmt,...); //串口2的专用printf函数
void USART3_printf(char* fmt,...); //串口3的专用printf函数
#endif
第二步 main.c 中调用函数
1️⃣:在最上方包含usart的头文件
#include "usart.h"
2️⃣:在USART头文件选择需要的串口初始化函数,拷贝到main.c中,并设置波特率(例如9600)。
USART1_Init(9600);
3️⃣:接下来就可以自由自在的使用printf函数了😄
USART1_printf("Hello World!");
main.c事例
#include "stm32f10x.h"
#include "stm32f10x_conf.h"
#include "usart.h"
int main(void)
{
USART1_Init(9600);
USART1_printf("Hello World!");
while(1);
}
USART1_printf 的优点
- 1、可以多个串口使用
USART1_printf("wellcom !");
USART2_printf("wellcom !");
USART3_printf("wellcom !");
- 2、用法与printf一致同样方便简介。
如何改写printf 🗝
在C文件中添加下列代码
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE {
int handle;
};
FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x){
x = x;
}
//重定义fputc函数
int fputc(int ch, FILE *f){
while((USART_n->SR&0X40)==0)
;//循环发送,直到发送完毕
USART_n->DR = (u8) ch;
return ch;
}
USART1_printf 的源码 🗝
void USART1_printf(char *fmt, ...)
{
static unsigned char Usartx_TxBuff[USART1_REC_LEN];
unsigned int i, length;
va_list ap; //va_list 可变参数列表,存参数地址
va_start(ap, fmt); //获取可变参数地址 fmt地址赋给ap
/*使用参数列表发送格式化输出到字符串,函数功能将可变参数格式化输出到一个字符数组*/
vsprintf((char *)Usartx_TxBuff, fmt, ap); //fmt中内容赋给Usart3_TxBuff
va_end(ap); //清空参数列表
length = strlen((const char *)Usartx_TxBuff);
while ((USART1->SR & 0X40) == 0)
;
for (i = 0; i < length; i++)
{
USART1->DR = Usartx_TxBuff[i];
while ((USART1->SR & 0X40) == 0);
}
}
串口的初始化函数 📃
void USART1_Init(u32 bound){ //串口1初始化并启动
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_Init(USART1, &USART_InitStructure);
NVIC_Init(&NVIC_InitStructure);
USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);//(选择串口,选择中断方式,使能中断)
USART_Cmd(USART1, ENABLE); //使能串口
}