整理资料来源
- 【正点原子】 手把手教你学STM32单片机教学视频 嵌入式 之 F103-基于新战舰V
- NANO_STM32F103开发指南-HAL库版本_V1.0.pdf
- 其它网络操作等
词汇解释
pin:引脚
specifies:指定
configure:配置
STM32固件库
解释:类似于C语言编程中调用printf()一样,调用标准外设库的库函数。为开发者访问底层硬件提供一个中间API
STM32F10x_StdPeriph_Lib_V3.5.0
Libraries:
CMSIS:内核库文件
CoreSuport:
Cortex-M3核内外设函数文件夹,Cortcx-M3内核通用源文件core_cm3.c和Cortcx-M3内核通用头文core_cm3.h
STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm:启动代码文件
DeviceSuport:
设备外设支持函数文件夹,STM32F0x头文件stm32f10x.h和系统初始化文件system_stm32f10x.c
STM32F10x_StdPeriph_Driver:
存放ST为STM32F10x每个外设而编写的库函数源代码文件和头文件
创建Template模板模板自取
Template:
|—Systems/CORE:相关的启动文件以及内核文件,系统初始化文件system_stm32f10x.c
|—FWLib/HALLIB:存放ST为STM32F10x每个外设而编写的库函数源代码文件和头文件
|—|---Src:.c
|—|---Inc:.h
|—BSP/OBJ:存放用户自己编写的硬件驱动文件,比如LED.c、LED.h等
|—USER:存放main函数和中断程序。复制stm32f10x_conf.h、stm32f10x_it.c、stm32f10x_it.h和main.c
-
芯片型号Device:STMF103RB
-
其中 DebugConfig 文件夹用于存储一些调试配置文件,Listings 和 Objects 文件夹用来存储 MDK 编译过程的一些中间文件(可删)
-
把内核、启动文件、外设等相关的库文件添加进Keil工程
-
在“Target”选项页中设置晶振为8MHz,并勾选“Use MicroLIB”(使用Micro库)
-
在“Output”选项页中勾选“Create HEX File”,生成HEX文件
-
在工程设置窗口的“C/C++”选项页的“Define”框中输入两个宏:
USE_STDPERIPH_DRIVER , STM32F10X_MD目的:为了屏蔽编译器的默认搜索路径,转而使用添加到工程中的STM32F10x标准外设库,即使用STM32F10x标准外设库进行STM32的开发
-
在工程设置窗口的“C/C++”选项页的“Include Paths”中,将工程头文件.h添加进搜索路径中
-
单击Settings按钮,在弹出的界面中勾选中“Reset and Run”,选择“Erase Full Chip”,每次烧写都将擦除掉芯片上已有的内容
-
软件模拟仿真??
错误总结
Error: L6320W: Ignoring --entry command. Cannot find argument ‘Reset_Handler’.
Warning: L6320W: Ignoring --first command. Cannot find argument ‘__Vectors’.
通用目的的输入输出口
1. GPIO:General Purpose Input/Output
端口号:端口号通常以大写字母命名,从A开始,依次类推。例如,GPIOA、GPIOB、GPIOC、…等
引脚号:每个端口有16个I/O引脚,分别命名为0-15。例如,STM32F103RB微控制器的GPIOA端口有16个引脚,分别为PA0、PA1、PA2、PA3、…、PA14和PA15。
IO口8种模式:
1、输入浮空GPIO_Mode_IN_FLOATING:浮空(floating)就是逻辑器件的输入引脚即不接高电平,也不接低电平。由于逻辑器件的内部结构,当它输入引脚悬空时,相当于该引脚接了高电平。一般实际运用时,引脚不建议悬空,易受干扰。通俗讲就是让管脚什么都不接,浮空着。
2、输入上拉GPIO_IPU:上拉就是把电位拉高,比如拉到Vcc。上拉就是将不确定的信号通过一个电阻嵌位在高电平!电阻同时起限流作用!强弱只是上拉电阻的阻值不同,没有什么严格区分。
3、输入下拉GPIO_IPD:就是把电压拉低,拉到GND。与上拉原理相似
4、模拟输入GPIO_AIN:应用ADC模拟输入,或者低功耗下省电
5、开漏输出GPIO_OUT_OD:IO输出0接GND,IO输出1,悬空,需要外接上拉电阻,才能实现输出高电平。当输出为1时,IO口的状态由上拉电阻拉高电平,但由于是开漏输出模式,这样IO口也就可以由外部电路改变为低电平或不变。可以读IO输入电平变化,实现C51的IO双向功能
6、推挽输出GPIO_OUT_PP:高低电平,IO输出0-接GND, IO输出1 -接VCC,读输入值是未知的
7、复用功能的推挽输出GPIO_AF_PP:片内外设功能(I2C的SCL,SDA)
8、复用功能的开漏输出GPIO_AF_OD:片内外设功能(TX1,MOSI,MISO.SCK.SS)
- 复用开漏输出、复用推挽输出:可以理解为GPIO口被用作第二功能时的配置情况(即并非作为通用IO口使用)
- 通常有5种方式使用某个引脚功能,它们的配置方式如下:
1、作为普通GPIO输入:根据需要配置该引脚为浮空输入、带弱上拉输入或带弱下拉输入,同时不要使能该引脚对应的所有复用功能模块。
2、作为普通GPIO输出:根据需要配置该引脚为推挽输出或开漏输出,同时不要使能该引脚对应的所有复用功能模块。
3、作为普通模拟输入:配置该引脚为模拟输入模式,同时不要使能该引脚对应的所有复用功能模块。
4、作为内置外设的输入:根据需要配置该引脚为浮空输入、带弱上拉输入或带弱下拉输入,同时使能该引脚对应的某个复用功能模块。
5、作为内置外设的输出:根据需要配置该引脚为复用推挽输出或复用开漏输出,同时使能该引脚对应的所有复用功能模块。
注意如果有多个复用功能模块对应同一个引脚,只能使能其中之一,其它模块保持非使能状态。 比如要使用STM32F103VBT6的47、48脚的USART3功能,则需要配置47脚为复用推挽输出或复用开漏输出,配置48脚为某种输入模式,同时使能USART3并保持I2C2的非使能状态。 如果要使用STM32F103VBT6的47脚作为TIM2_CH3,则需要对TIM2进行重映射,然后再按复用功能的方式配置对应引脚。
2. IO口库函数介绍(官方库最终也是操作寄存器)
GPIO_Init参数:
GPIO_TypeDef* GPIOx:选择哪个GPIO端口
GPIO_InitTypeDef* GPIO_InitStruct:相关参数初始化
初始化示例代码
GPIO_InitTypeDef GPIO_InitStructure; //定义一个初始化化结构体,之后在这个结构体中设置参数
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC , ENABLE); //时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;//这里初始化了所有引脚,前提是这些IO口的配置方式一样
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;
GPIO_Init(GPIOC, &GPIO_InitStructure); //根据参数初始化,GPIOC组
GPIO_InitStructure.GPIO_Mode:
表示命名为GPIO_InitStructure的结构体(typedef struct)里面定义的GPIO_Mode。如下例
typedef struct
{
uint16_t GPIO_Pin; /*!< Specifies the GPIO pins to be configured.
This parameter can be any value of @ref GPIO_pins_define */GPIOSpeed_TypeDef GPIO_Speed; /*!< Specifies the speed for the selected pins.
This parameter can be a value of @ref GPIOSpeed_TypeDef */GPIOMode_TypeDef GPIO_Mode; /*!< Specifies the operating mode for the selected pins.
This parameter can be a value of @ref GPIOMode_TypeDef */
}GPIO_InitTypeDef;
跑马灯实验步骤
-
创建LED.c LED.h文件
.h文件要点:
写下公共宏定义和函数声明,可以被多个.c文件引用,避免重复代码
头文件中使用#ifndef、#define开始,#endif结尾,避免头文件内容被重复编译
#ifndef _LED_H #define _LED_H #include "stm32f10x.h"//必须引用,包含所有外设寄存器和结构体定义,这样就可以引用具体可函数就不会报错 void LEDInit(void); void LEDdisplay(void); #endif
-
使能IO口时钟
时钟库文件stm32f10x_rcc.c
源文件
void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState);
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
-
AHB总线时钟
-
APB1低速外设:TIM2~7、TIM12、TIM13、TIM14、WWDG、SPI2、SPI3、USART2、USART3、UART4、UART5、12C1、12C2、USB、CAN1、CAN2、BKP、PWR、DAC、CEC
-
APB2高速外设:AFIO、GPIOAG、ADC12、TIM1、SPI1、TIM8、USART1、ADC3、TIM15、TIM16、TIM17、TIM9、TIM10、TIM11
例如使能APB2的GPIOC时钟:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC , ENABLE);
- 初始化IO口模式。调用函数GPIO_Init()
- 操作IO口,输出高低电平,高GPIO_SetBits()、低GPIO_ResetBits()
#include "Led.h"
#include "stm32f10x.h"
void LEDInit()
{
GPIO_InitTypeDef GPIO_InitStructure;
SystemInit();
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC , ENABLE);
//定义一个初始化结构体,因为要传入的参数不止一个
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; //所有引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;
GPIO_Init(GPIOC, &GPIO_InitStructure); //根据参数初始化,GPIOC端口
GPIO_Write(GPIOC,0x00);
}
void LEDdisplay()
{
u32 i;
GPIO_SetBits(GPIOC, GPIO_Pin_All);
GPIO_ResetBits(GPIOC, GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_6);
for(i=0;i<18000000;i++) ;
while(1)
{
//方法一GPIO_SetBits£¬GPIO_ResetBits
/*
GPIO_ResetBits(GPIOC, GPIO_Pin_1);
GPIO_SetBits(GPIOC, GPIO_Pin_0);
for(i=0;i<12000000;i++);
GPIO_SetBits(GPIOC, GPIO_Pin_1);
for(i=0;i<12000000;i++);
GPIO_ResetBits(GPIOC, GPIO_Pin_All);
GPIO_SetBits(GPIOC, GPIO_Pin_1);
for(i=0;i<18000000;i++)
GPIO_ResetBits(GPIOC, GPIO_Pin_All);
GPIO_SetBits(GPIOC, GPIO_Pin_2);
*/
//方法二GPIO_Write
GPIO_Write(GPIOC, 0xfe);
for(i=0;i<6000000;i++) ;
GPIO_Write(GPIOC, 0xfd);
for(i=0;i<6000000;i++) ;
GPIO_Write(GPIOC, 0xfb);
for(i=0;i<6000000;i++) ;
GPIO_Write(GPIOC, 0xf7);
for(i=0;i<6000000;i++) ;
GPIO_Write(GPIOC, 0xef);
for(i=0;i<6000000;i++) ;
GPIO_Write(GPIOC, 0xdf);
for(i=0;i<6000000;i++) ;
GPIO_Write(GPIOC, 0xbf);
for(i=0;i<6000000;i++) ;
GPIO_Write(GPIOC, 0x7f);
for(i=0;i<6000000;i++) ;
}
}
蜂鸣器实验
-
蜂鸣器简介
有源蜂鸣器自带了震荡电路,一通电就会发声;无源蜂鸣器则没有自带震荡电路,必须外部提供 2~5Khz 左右的方波驱动,才能发声。
-
硬件设计
蜂鸣器的驱动信号连接在 STM32 的 PB8 上。图中我们用到一个 PNP 三极管(S8550)放大电流来驱动蜂鸣器,R25 主要用于控制 PNP 管饱和导通作用。当 PB.8 输出低电平的时候,蜂鸣器将发声,当 PB.8 输出高电平的时候,蜂鸣器停止发声。
-
软件设计
beep.h
#ifndef _BEEP_H
#define _BEEP_H
#include "stm32f10x.h"
#include "sys.h"
void BEEP_Init(void);
#endif
beep.c
#include "beep.h"
//蜂鸣器IO口初始化
void BEEP_Init(void){
GPIO_InitTypeDef GPIO_Initure;
//开启GPIOB时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_Initure.GPIO_Pin=GPIO_Pin_8;//开启蜂鸣器连接的PB8引脚
GPIO_Initure.GPIO_Mode=GPIO_Mode_Out_PP;//推挽输出
GPIO_Initure.GPIO_Speed=GPIO_Speed_50MHz;//高速
GPIO_Init(GPIOB,&GPIO_Initure);
//BEEP引脚输入高电平,三级管导通,蜂鸣器发声。反之,截止,蜂鸣器关闭。
GPIO_SetBits(GPIOB,GPIO_Pin_8);//输出1,关闭蜂鸣器输出
}
main.c
#