文章目录
一、学习任务
- 学习相关资料,说名基于寄存器与基于固件库的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.c
#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.c
#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.c
#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.c
#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 实验文件
链接:书籍配套例程-F103VE指南者
提取码:k5rw
下载完成后如箭头所示打开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[i] = USART_ReceiveData(USART1);
}
if(ucTemp[i] == '!')
{
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文件,然后进行烧写