本文共 5699 字,大约阅读时间需要 18 分钟。
《STM32从零开始学习历程》
本实验是在的基础上完成的,可以先学习实验1,然后再进行此实验,如果实验1能够理解并且处理的游刃有余,那么实验2将是小菜一碟了,本着从零开始的目的,我们还是一步一步,讲的详细一些。
软件:Keil μVision5 v5.33(MDK5),串口助手XCOM V2.6
环境:Windows10 Enterprise x64 芯片:STM32F406ZGT6 设备:正点原子STM32F4探索者开发板 仿真器:ST-Link 参考手册: [野火EmbedFire]《STM32库开发实战指南——基于野火霸天虎开发板》 [正点原子]STM32F4开发指南-库函数版本_V1.2 [ST]《STM32F4xx中文参考手册》 [ST]《STM32F407xx》通过串口助手向STM32发送特定的指令,实现对LED灯的控制。
如: 发送字符“1”-----》LED1亮 发送字符“2”-----》LED2亮 发送字符“3”-----》LED1&LED2亮 发送字符“4”-----》LED1灭 发送字符“5”-----》LED2灭 发送字符“6”-----》LED1&LED2灭查阅开发板手册以及芯片手册非常重要!

 
   小结:由硬件连接图与电路设计图可以看出,LED1与LED2连接于芯片的PF9与PF10端口,在软件设计时需要对这两个GPIO进行初始化设置。
由电路设计图可以看出,如果PF9与PF10端口为高电平(3.3V),则没有电压流过LED灯管,只有当PF9与PF10为低电平时才有电流流过LED灯管,因此只有使用GPIO_ResetBits()函数才可以点亮LED。本实验设计分为三个部分:USART初始化子函数、LED初始化子函数,主函数。
1. 初始化USART初始化USART串口函数:
void uart_init(u32 bound){    //GPIO端口设置    GPIO_InitTypeDef GPIO_InitStructure;											//定义初始化结构体变量	USART_InitTypeDef USART_InitStructure;		RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE); 							//使能GPIOA时钟	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);							//使能USART1时钟 	//串口1对应引脚复用映射	GPIO_PinAFConfig(GPIOB,GPIO_PinSource6,GPIO_AF_USART1); 						//GPIOB6复用为USART1	GPIO_PinAFConfig(GPIOB,GPIO_PinSource7,GPIO_AF_USART1);							//GPIOB7复用为USART1		//USART1端口配置    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; 							//GPIOB6与GPIOB7	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;									//复用功能	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;								//速度50MHz	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 									//推挽复用输出	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; 									//上拉	GPIO_Init(GPIOB,&GPIO_InitStructure); 											//初始化PB6,PB7    //USART1 初始化设置	USART_InitStructure.USART_BaudRate = bound;										//波特率设置	USART_InitStructure.USART_WordLength = USART_WordLength_8b;						//字长为8位数据格式	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); 										//初始化串口1	    USART_Cmd(USART1, ENABLE);  													//使能串口1 	}   重定向c库函数printf到串口,重定向后可使用printf函数:
在进行重定向函数编写时首先需要完成如下两个操作:
(1)在MDK5界面中点击“ ”图标,将“USE MicroLIB”打上勾勾。
”图标,将“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);}   关于重定向函数的一些解释:
对于上文重定向printf、scanf与getchar函数读者可能对此有疑惑,故在此做一下说明。
重定向:
就是指重新定义C库函数。对于printf()函数而言,printf只是一个宏定义,实际上调用的是fputc()函数,为了能够使用printf()函数直接向串口发送数据,需要重定向fputc()函数。同理,重定向scanf()函数也是这个意思。
FILE *f是单片机函数重定向的固定用法,因为C语言和单片机对fputc(),fgetc()函数的定义是不同的,在C中,标准的参数为int xxx , FILE *x,如果没有FILE *x 这个指针变量,则无法实现重定向,因此这是一个固定用法。
在定义函数时,FILE *x 这个指针变量必须有,但是函数主体中可以不使用。2. 初始化LED
void LED_Init(void){    	   GPIO_InitTypeDef  GPIO_InitStructure;  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);										//使能GPIOF时钟  //GPIOF9,GPIOF10初始化设置  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;									//LED0和LED1对应IO口  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;												//普通输出模式  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;											//推挽输出  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;										//100MHz  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;												//上拉  GPIO_Init(GPIOF, &GPIO_InitStructure);													//初始化GPIO	  GPIO_SetBits(GPIOF,GPIO_Pin_9 | GPIO_Pin_10);												//GPIOF9,F10设置高,灯灭}   3. 主函数
对于主函数的编写比较清晰,先对串口、LED进行初始化调用,然后使用Switch对串口接收到的信息进行匹配,从而执行相应的动作。
此外还可以额外定义一个全局函数Show_Message()用来向串口发送提示信息。static void Show_Message(void);																//函数申明int main(void){    char ch;																				//开辟一个字符存储空间	delay_init(168);																		//延时初始化 	uart_init(115200);																		//串口初始化波特率为115200	LED_Init();		  																		//初始化与LED连接的硬件接口  	Show_Message();																			//显示提示信息		while(1)	{		ch = getchar();		if(ch != '\0')		{		printf("接收到字符:%c\n",ch);		}		switch(ch)		{			case '1':				GPIO_ResetBits(GPIOF,GPIO_Pin_9);  //LED0对应引脚GPIOF.9拉低,亮 ,等同LED0=0;			break;						case '2':				GPIO_ResetBits(GPIOF,GPIO_Pin_10);  			break;						case '3':				GPIO_ResetBits(GPIOF,GPIO_Pin_9 | GPIO_Pin_10);			break;						case '4':				GPIO_SetBits(GPIOF,GPIO_Pin_9);			break;						case '5':				GPIO_SetBits(GPIOF,GPIO_Pin_10);			break;						case '6':				GPIO_SetBits(GPIOF,GPIO_Pin_9 | GPIO_Pin_10);			break;						default:				Show_Message();			break;		}	}}static void Show_Message(void)															//定义全局函数{	printf("\n 串口通讯控制实验: \n");	printf("指令 -----------  跑马灯\n");	printf("  1  -----------   LED1  ON \n");	printf("  2  -----------   LED2  ON \n");	printf("  3  -----------  LED1&2 ON \n");	printf("  4  -----------   LED1  OFF \n");	printf("  5  -----------   LED2  OFF \n");	printf("  6  -----------  LED1&2 OFF \n");}   编译,下载程序。
使用XCOM串口调试助手,会发现接收框不断地有Show_Message()中编写的提示信息发送过来。 在发送框中,输入3,点击发送。如下图所示,LED1&0被点亮,串口接收到指令3。
其实本实验不难,是基于实验1进行了一些小改动而来的,主要是要了解下重定向。
有了此实验的基础,对于后期的实验或者工程会有很大的帮助。 如有不足之处还请各位大佬及时指出!转载地址:http://imwcz.baihongyu.com/