1.硬件设计流程
2.程序设计流程
1.串口初始化时钟使能:RCC_APBxPeriphClockCmd();
GPIO初始化时钟使能:RCC_AHBxPeriphClockCmd();
2.GPIO端口模式配置:GPIO_Init();
3.串口参数初始化:USART_Init();
4.串口使能:USART_Cmd();
5.重定向printf与scanf函数;
6.LED初始化:LED_Init();
初始化USART串口函数:
#include "Usart.h"
void Usart_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
USART_InitTypeDef USART_InitStruct;
//打开串口GPIO的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
//将USARTTx的GPIO配置为推挽复用模式
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; //推挽复用模式
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
// 将 USART Rx 的 GPIO 配置为浮空输入模式
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入模式
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
// 配置串口的工作参数
// 配置波特率
USART_InitStruct.USART_BaudRate = 115200;
// 配置硬件流控制
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
// 配置工作模式,收发一起
USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
// 配置校验位
USART_InitStruct.USART_Parity = USART_Parity_No;
// 配置停止位
USART_InitStruct.USART_StopBits = USART_StopBits_1;
// 配置 针数据字长
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
// 完成串口的初始化配置
USART_Init(USART1,&USART_InitStruct);
// 使能串口
USART_Cmd(USART1,ENABLE);
}
重定向c库函数printf到串口,重定向后可使用printf函数:
在进行重定向函数编写时首先需要完成如下两个操作:
(1)在MDK5界面中点击“”图标,将“USE MicroLIB”打上勾勾。
(2)在定义文件中需要包含 #include “stdio.h” 头文件。
int fputc(int ch , FILE *f)
{
USART_SendData(USART1,(uint8_t) ch );
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);
//USART_FLAG_TXE:发送数据寄存器中的数据有没有被取走
return (ch);
}
重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数:
int fgetc(FILE *f)
{
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);
//USART_FLAG_TXE:发送数据寄存器中的数据有没有被取走
return (int)USART_ReceiveData(USART1);
}
重定向:
就是指重新定义C库函数。对于printf()函数而言,printf只是一个宏定义,实际上调用的是fputc()函数,为了能够使用printf()函数直接向串口发送数据,需要重定向fputc()函数。同理,重定向scanf()函数也是这个意思。
FILE *f是单片机函数重定向的固定用法,因为C语言和单片机对fputc(),fgetc()函数的定义是不同的,在C中,标准的参数为int xxx , FILE *x,如果没有FILE *x 这个指针变量,则无法实现重定向,因此这是一个固定用法。
在定义函数时,FILE *x 这个指针变量必须有,但是函数主体中可以不使用。
2. 初始化LED
#include "Led.h"
void LED_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE); //开启时钟
GPIO_InitTypeDef GPIO_InitStruct; //定义GPIO结构体
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5; //选用引脚5
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOE,&GPIO_InitStruct);
GPIO_SetBits(GPIOE,GPIO_Pin_5); //上电默认熄灭
}
void LED_ON()
{
GPIO_ResetBits(GPIOE,GPIO_Pin_5); //灯亮
}
void LED_OFF()
{
GPIO_SetBits(GPIOE,GPIO_Pin_5); //灯灭
}
3. 主函数
#include "stm32f10x.h" // Device header
#include "Usart.h"
#include "Led.h"
#include "Delay.h"
static void Show_Message(void); //函数声明
int main(void)
{
char ch = 0;
/* 初始化 USART 配置模式为 115200 8-N-1,中断接收 */
LED_Init();
Usart_Init();
Show_Message();
while(1)
{
ch = getchar();
if( ch != '\0')
{
Delay_ms(100);
printf("接收到字符:%c\n",ch);
}
switch(ch)
{
case '1':
LED_ON();
break;
case '2':
LED_OFF();
break;
default:
Delay_ms (500);
Show_Message();
break;
}
}
}
static void Show_Message(void) //定义全局函数
{
printf("\n 串口通讯控制实验: \n");
printf("指令 ----------- LED亮灭\n");
printf(" 1 ----------- LED1 ON \n");
printf(" 2 ----------- LED1 OFF \n");
}