一、学习任务
- 学习相关资料,说名基于寄存器与基于固件库的stm32 LED流水灯例子的编程方式有什么差异。
- 学习和阅读“零死角玩转STM32F103–指南者”文档中的第20、21章内容,完成STM32的USART窗口通讯程序,要求:1)设置波特率为115200,1位停止位,无校验位。2)STM32系统给上位机(win10)连续发送“hello windows!”,上位机接收程序可以使用“串口调试助手“,也可自己编程。3)当上位机给stm32发送“Stop,stm32”后,stm32停止发送。
二、学习内容
1.基于寄存器与基于固件库的stm32 LED流水灯编程方式差异
1.1基于寄存器的stm32 LED流水灯程序
1.1.1寄存器简介
寄存器的功能是存储二进制代码,它是由具有存储功能的触发器组合起来构成的。一个触发器可以存储1位二进制代码,故存放n位二进制代码的寄存器,需用n个触发器来构成。
按照功能的不同,可将寄存器分为基本寄存器和移位寄存器两大类。基本寄存器只能并行送入数据,也只能并行输出。移位寄存器中的数据可以在移位脉冲作用下依次逐位右移或左移,数据既可以并行输入、并行输出,也可以串行输入、串行输出,还可以并行输入、串行输出,或串行输入、并行输出,十分灵活,用途也很广。
1.1.2.代码
led.h编程
#ifndef __LED_H#define __LED_H #include "sys.h"//LED端口定义#define LED0 PBout(5) // DS0#define LED1 PEout(5) // DS1 void LED_Init(void); //初始化 #endif
led.cwindows
#include "led.h"//初始化PB5和PE5为输出口.并使能这两个口的时钟 //LED IO初始化void LED_Init(void){ RCC->APB2ENR|=1<<3; //使能PORTB时钟 RCC->APB2ENR|=1<<6; //使能PORTE时钟 GPIOB->CRL&=0XFF0FFFFF; GPIOB->CRL|=0X00300000;//PB.5 推挽输出 GPIOB->ODR|=1<<5; //PB.5 输出高 GPIOE->CRL&=0XFF0FFFFF; GPIOE->CRL|=0X00300000;//PE.5推挽输出 GPIOE->ODR|=1<<5; //PE.5输出高 }
main.csvg
#include "sys.h"#include "usart.h" #include "delay.h" #include "led.h"int main(void){ Stm32_Clock_Init(9);//系统时钟设置 delay_init(72); //延时初始化 LED_Init(); //初始化与LED链接的硬件接口 while(1) { LED0=0; //低电平有效 LED1=1; delay_ms(1000); LED0=1; LED1=0; delay_ms(1000); } }
1.2基于固件库的stm32 LED流水灯程序
1.2.1固件库概述
固件是介于软件和硬件之间的产品,给开发者访问底层硬件提供一个中间的API,大大提高应用程序开发效率。CMSIS: ARM Cortex™ 微控制器软件接口标准(CMSIS:Cortex Microcontroller Software Interface Standard) 是 Cortex-M 处理器系列的与供应商无关的硬件抽象层,使用CMSIS,可以为处理器和外设实现一致且简单的软件接口,从而简化软件的重用、缩短微控制器新开发人员的学习过程,并缩短新设备的上市时间。
1.2.2代码
led.h学习
#ifndef __LED_H#define __LED_H #include "sys.h"#define LED0 PBout(5)// PB5#define LED1 PEout(5)// PE5 void LED_Init(void);//初始化 #endif
led.cui
#include "led.h"//初始化PB5和PE5为输出口.并使能这两个口的时钟 //LED IO初始化void LED_Init(void){ GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE); //使能PB,PE端口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED0-->PB.5 端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化GPIOB.5 GPIO_SetBits(GPIOB,GPIO_Pin_5); //PB.5 输出高 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED1-->PE.5 端口配置, 推挽输出 GPIO_Init(GPIOE, &GPIO_InitStructure); //推挽输出 ,IO口速度为50MHz GPIO_SetBits(GPIOE,GPIO_Pin_5); //PE.5 输出高 }
main.cspa
#include "sys.h"#include "delay.h"#include "usart.h"#include "led.h" int main(void) { delay_init(); //延时函数初始化 LED_Init(); //初始化与LED链接的硬件接口 while(1) { LED0=0; LED1=1; delay_ms(300); //延时300ms LED0=1; LED1=0; delay_ms(300); //延时300ms } } /** *****************下面注视的代码是经过调用库函数来实现IO控制的方法***************************************** int main(void) { delay_init(); //初始化延时函数 LED_Init(); //初始化LED端口 while(1) { GPIO_ResetBits(GPIOB,GPIO_Pin_5); //LED0对应引脚GPIOB.5拉低,亮 等同LED0=0; GPIO_SetBits(GPIOE,GPIO_Pin_5); //LED1对应引脚GPIOE.5拉高,灭 等同LED1=1; delay_ms(300); //延时300ms GPIO_SetBits(GPIOB,GPIO_Pin_5); //LED0对应引脚GPIOB.5拉高,灭 等同LED0=1; GPIO_ResetBits(GPIOE,GPIO_Pin_5); //LED1对应引脚GPIOE.5拉低,亮 等同LED1=0; delay_ms(300); //延时300ms } }
1.3 差异
仔细观察源代码发现主要是led.c中的LED_Init()函数有很大的差别。基于寄存器的主要是使用指针指向地址进行使能和赋值;基于固件库主要使用的函数包进行使能和赋值。在小工程中可以看出使用寄存器和固件库是没有多大差别的,但从实现多功能和多端口的工程设计来看,使用固件库可以大大减少开发时间,提高工作效率。
使用固件库,目前比较多的例程是使用固件库编写的。官方的例子也都采用固件库方式。特点就是简单,易于理解,资料多。如果你没有CortexM系列内核的开发基础,建议从固件库开始玩起。等有一定基础,或是特别需要时再用寄存器。
使用寄存器,想要深入理解CortexM3内核或是需要为了获得更好的可移植性,学习寄存器编程会比较有帮助。但是从专业的角度上看,寄存器更贴近底层,对外设的工作原理和运行机理会有更深的理解。
2.STM32的USART窗口通讯程序
2.1 实验环境
开发板:野火指南者(STM32F103)
STM32库版本:STM32F10x_StdPeriph_Lib_V3.5.0
IDE:KEIL5
使用到的串口:USART1
硬件原理图:
2.2 实验文件
下载完成后如箭头所示打开keil文件。
2.3.相关代码及修改
2.3.1 找到stm32f10x_it.c,及main.c;
2.3.2 代码
stm32f10x_it.c:
int i=0;uint8_t ucTemp[50];void DEBUG_USART_IRQHandler(void){ if(USART_GetITStatus(DEBUG_USARTx,USART_IT_RXNE)!=RESET) { ucTemp
= USART_ReceiveData(USART1); } if(ucTemp == '!') { if(ucTemp[i-1] == '2'&&ucTemp[i-2] == '3'&&ucTemp[i-3] == 'm'&&ucTemp[i-4] == 't'&&ucTemp[i-5] == 's'&&ucTemp[i-6] == ' ') if(ucTemp[i-7] == 'p'&&ucTemp[i-8] == 'o'&&ucTemp[i-9] == 't'&&ucTemp[i-10] == 's') { printf("收 到!"); while(1); } } i++;}main.c:
#include "stm32f10x.h"#include "bsp_usart.h"void delay(uint32_t count){ while(count--);}int main(void){ USART_Config(); while(1) { printf("hello windows!n"); delay(5000000); } }2.3.3.修改如下
stm32f10x_it.c:
main.c:
2.3.4编译及生成hex文件
2.4.烧录程序
2.4.1 连接开发板
2.4.2打开串口下载器选择刚编译生成的.hex文件,然后进行烧写
一、学习任务
- 学习相关资料,说名基于寄存器与基于固件库的stm32 LED流水灯例子的编程方式有什么差异。
- 学习和阅读“零死角玩转STM32F103–指南者”文档中的第20、21章内容,完成STM32的USART窗口通讯程序,要求:1)设置波特率为115200,1位停止位,无校验位。2)STM32系统给上位机(win10)连续发送“hello windows!”,上位机接收程序可以使用“串口调试助手“,也可自己编程。3)当上位机给stm32发送“Stop,stm32”后,stm32停止发送。
二、学习内容
1.基于寄存器与基于固件库的stm32 LED流水灯编程方式差异
1.1基于寄存器的stm32 LED流水灯程序
1.1.1寄存器简介
寄存器的功能是存储二进制代码,它是由具有存储功能的触发器组合起来构成的。一个触发器可以存储1位二进制代码,故存放n位二进制代码的寄存器,需用n个触发器来构成。
按照功能的不同,可将寄存器分为基本寄存器和移位寄存器两大类。基本寄存器只能并行送入数据,也只能并行输出。移位寄存器中的数据可以在移位脉冲作用下依次逐位右移或左移,数据既可以并行输入、并行输出,也可以串行输入、串行输出,还可以并行输入、串行输出,或串行输入、并行输出,十分灵活,用途也很广。
1.1.2.代码
led.h编程
#ifndef __LED_H#define __LED_H #include "sys.h"//LED端口定义#define LED0 PBout(5) // DS0#define LED1 PEout(5) // DS1 void LED_Init(void); //初始化 #endif
led.cwindows
#include "led.h"//初始化PB5和PE5为输出口.并使能这两个口的时钟 //LED IO初始化void LED_Init(void){ RCC->APB2ENR|=1<<3; //使能PORTB时钟 RCC->APB2ENR|=1<<6; //使能PORTE时钟 GPIOB->CRL&=0XFF0FFFFF; GPIOB->CRL|=0X00300000;//PB.5 推挽输出 GPIOB->ODR|=1<<5; //PB.5 输出高 GPIOE->CRL&=0XFF0FFFFF; GPIOE->CRL|=0X00300000;//PE.5推挽输出 GPIOE->ODR|=1<<5; //PE.5输出高 }
main.csvg
#include "sys.h"#include "usart.h" #include "delay.h" #include "led.h"int main(void){ Stm32_Clock_Init(9);//系统时钟设置 delay_init(72); //延时初始化 LED_Init(); //初始化与LED链接的硬件接口 while(1) { LED0=0; //低电平有效 LED1=1; delay_ms(1000); LED0=1; LED1=0; delay_ms(1000); } }
1.2基于固件库的stm32 LED流水灯程序
1.2.1固件库概述
固件是介于软件和硬件之间的产品,给开发者访问底层硬件提供一个中间的API,大大提高应用程序开发效率。CMSIS: ARM Cortex™ 微控制器软件接口标准(CMSIS:Cortex Microcontroller Software Interface Standard) 是 Cortex-M 处理器系列的与供应商无关的硬件抽象层,使用CMSIS,可以为处理器和外设实现一致且简单的软件接口,从而简化软件的重用、缩短微控制器新开发人员的学习过程,并缩短新设备的上市时间。
1.2.2代码
led.h学习
#ifndef __LED_H#define __LED_H #include "sys.h"#define LED0 PBout(5)// PB5#define LED1 PEout(5)// PE5 void LED_Init(void);//初始化 #endif
led.cui
#include "led.h"//初始化PB5和PE5为输出口.并使能这两个口的时钟 //LED IO初始化void LED_Init(void){ GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE); //使能PB,PE端口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED0-->PB.5 端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化GPIOB.5 GPIO_SetBits(GPIOB,GPIO_Pin_5); //PB.5 输出高 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED1-->PE.5 端口配置, 推挽输出 GPIO_Init(GPIOE, &GPIO_InitStructure); //推挽输出 ,IO口速度为50MHz GPIO_SetBits(GPIOE,GPIO_Pin_5); //PE.5 输出高 }
main.cspa
#include "sys.h"#include "delay.h"#include "usart.h"#include "led.h" int main(void) { delay_init(); //延时函数初始化 LED_Init(); //初始化与LED链接的硬件接口 while(1) { LED0=0; LED1=1; delay_ms(300); //延时300ms LED0=1; LED1=0; delay_ms(300); //延时300ms } } /** *****************下面注视的代码是经过调用库函数来实现IO控制的方法***************************************** int main(void) { delay_init(); //初始化延时函数 LED_Init(); //初始化LED端口 while(1) { GPIO_ResetBits(GPIOB,GPIO_Pin_5); //LED0对应引脚GPIOB.5拉低,亮 等同LED0=0; GPIO_SetBits(GPIOE,GPIO_Pin_5); //LED1对应引脚GPIOE.5拉高,灭 等同LED1=1; delay_ms(300); //延时300ms GPIO_SetBits(GPIOB,GPIO_Pin_5); //LED0对应引脚GPIOB.5拉高,灭 等同LED0=1; GPIO_ResetBits(GPIOE,GPIO_Pin_5); //LED1对应引脚GPIOE.5拉低,亮 等同LED1=0; delay_ms(300); //延时300ms } }
1.3 差异
仔细观察源代码发现主要是led.c中的LED_Init()函数有很大的差别。基于寄存器的主要是使用指针指向地址进行使能和赋值;基于固件库主要使用的函数包进行使能和赋值。在小工程中可以看出使用寄存器和固件库是没有多大差别的,但从实现多功能和多端口的工程设计来看,使用固件库可以大大减少开发时间,提高工作效率。
使用固件库,目前比较多的例程是使用固件库编写的。官方的例子也都采用固件库方式。特点就是简单,易于理解,资料多。如果你没有CortexM系列内核的开发基础,建议从固件库开始玩起。等有一定基础,或是特别需要时再用寄存器。
使用寄存器,想要深入理解CortexM3内核或是需要为了获得更好的可移植性,学习寄存器编程会比较有帮助。但是从专业的角度上看,寄存器更贴近底层,对外设的工作原理和运行机理会有更深的理解。
2.STM32的USART窗口通讯程序
2.1 实验环境
开发板:野火指南者(STM32F103)
STM32库版本:STM32F10x_StdPeriph_Lib_V3.5.0
IDE:KEIL5
使用到的串口:USART1
硬件原理图:
2.2 实验文件
下载完成后如箭头所示打开keil文件。
2.3.相关代码及修改
2.3.1 找到stm32f10x_it.c,及main.c;
2.3.2 代码
stm32f10x_it.c:
int i=0;uint8_t ucTemp[50];void DEBUG_USART_IRQHandler(void){ if(USART_GetITStatus(DEBUG_USARTx,USART_IT_RXNE)!=RESET) { ucTemp
= USART_ReceiveData(USART1); } if(ucTemp == '!') { if(ucTemp[i-1] == '2'&&ucTemp[i-2] == '3'&&ucTemp[i-3] == 'm'&&ucTemp[i-4] == 't'&&ucTemp[i-5] == 's'&&ucTemp[i-6] == ' ') if(ucTemp[i-7] == 'p'&&ucTemp[i-8] == 'o'&&ucTemp[i-9] == 't'&&ucTemp[i-10] == 's') { printf("收 到!"); while(1); } } i++;}main.c:
#include "stm32f10x.h"#include "bsp_usart.h"void delay(uint32_t count){ while(count--);}int main(void){ USART_Config(); while(1) { printf("hello windows!n"); delay(5000000); } }2.3.3.修改如下
stm32f10x_it.c:
main.c:
2.3.4编译及生成hex文件
2.4.烧录程序
2.4.1 连接开发板
2.4.2打开串口下载器选择刚编译生成的.hex文件,然后进行烧写
举报