stm32 STM32是ST公司基于ARM Cortex-M内核开发的32位微控制器
ARM内核
stm32F103C8T6 采用Cortex-M3内核 ,发布于2004年10月。
片上资源/外设
英文缩写
名称
英文缩写
名称
NVIC
嵌套向量中断控制器
CAN
CAN通信
SysTick
系统滴答定时器
USB
USB通信
RCC
复位和时钟控制
RTC
实时时钟
GPIO
通用IO口
CRC
CRC校验
AFIO
复用IO口
PWR
电源控制
EXTI
外部中断
BKP
备份寄存器
TIM
定时器
IWDG
独立看门狗
ADC
模数转换器
WWDG
窗口看门狗
DMA
直接内存访问
DAC
数模转换器
USART
同步/异步串口通信
SDIO
SD卡接口
I2C
I2C通信
FSMC
可变静态存储控制器
SPI
SPI通信
USB OTG
USB主机接口
命名规则
系统结构
引脚定义
红色:电源相关引脚
蓝色:最小系统相关引脚
绿色:IO口、功能口
有FT可以接上5V电压,没有FT只能容忍3.3V电压。
主功能:上电默认功能
stm32采用分区供电,有多个供电引脚
存储器映像
启动配置
最小系统电路
STM32核心板
C语言数据类型
关键字
位数
表示范围
stdint关键字
ST关键字
char
8
-128 ~ 127
int8_t
s8
unsigned char
8
0 ~ 255
uint8_t
u8
short
16
-32768 ~ 32767
int16_t
s16
unsigned short
16
0 ~ 65535
uint16_t
u16
int
32
-2147483648 ~ 2147483647
int32_t
s32
unsigned int
32
0 ~ 4294967295
uint32_t
u32
long
32
-2147483648 ~ 2147483647
unsigned long
32
0 ~ 4294967295
long long
64
-(2^64)/2 ~ (2^64)/2-1
int64_t
unsigned long long
64
0 ~ (2^64)-1
uint64_t
float
32
-3.4e38 ~ 3.4e38
double
64
-1.7e308 ~ 1.7e308
typedef和define的区别
(1)原理不同
define是C语言中定义的语法,是预处理指令,在预处理时进行简单而机械的字符串替换,不作正确性检查,只有在编译已被展开的源程序时才会发现可能的错误并报错。 typedef是关键字,在编译时处理,有类型检查功能。它在自己的作用域内给一个已经存在的类型一个别名,但不能在一个函数定义里面使用typedef。用typedef定义数组、指针、结构等类型会带来很大的方便,不仅使程序书写简单,也使意义明确,增强可读性。
(2)功能不同
typedef用来定义类型的别名,起到类型易于记忆的功能。另一个功能是定义机器无关的类型。如定义一个REAL的浮点类型,在目标机器上它可以获得最高的精度:typedef long double REAL, 在不支持long double的机器上,看起来是这样的,typedef double REAL,在不支持double的机器上,是这样的,typedef float REAL
define不只是可以为类型取别名,还可以定义常量、变量、编译开关等。 (3)作用域不同
define没有作用域的限制,只要是之前预定义过的宏,在以后的程序中都可以使用,而typedef有自己的作用域。 typedef和define有什么区别_define和typedef的区别-CSDN博客
结构体struct:数据打包,不同类型变量的集合,因为结构体变量类型较长,所以通常用typedef更改变量类型名。
枚举enum:定义一个取值受限制的整型变量,用于限制变量取值范围;宏定义的集合
STM32新建工程 工程架构
步骤
建立工程文件夹,Keil中新建工程,选择型号
工程文件夹里建立Start、Library、User等文件夹,复制固件库里面的文件到工程文件夹,保持工程独立性
工程里对应建立Start、Library、User等同名称的分组,然后将文件夹内的文件添加到工程分组里
工程选项,C/C++,Include Paths内声明所有包含头文件的文件夹
工程选项,C/C++,Define内定义USE_STDPERIPH_DRIVER
工程选项,Debug,下拉列表选择对应调试器,Settings,Flash Download里勾选Reset and Run
这里比较复杂直接看视频就行,下面是一个demo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include "stm32f10x.h" int main (void ) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC,&GPIO_InitStructure); GPIO_ResetBits(GPIOC,GPIO_Pin_13); while (1 ) { } }
GPIO 基本结构
GPIO位结构
推挽模式(强推输出模式):P-MOS,N-MOS均有效,STM32对IO口有绝对的控制权。
开漏模式:只有N-MOS工作,只有低电平有驱动能力,可以作为通信协议的驱动方式,输出5V电平信号
关闭模式:输出关闭,端口的电平由外部信号控制
GPIO模式
模式名称
性质
特征
浮空输入
数字输入
可读取引脚电平,若引脚悬空,则电平不确定
上拉输入
数字输入
可读取引脚电平,内部连接上拉电阻,悬空时默认高电平
下拉输入
数字输入
可读取引脚电平,内部连接下拉电阻,悬空时默认低电平
模拟输入
模拟输入
GPIO无效,引脚直接接入内部ADC
开漏输出
数字输出
可输出引脚电平,高电平为高阻态,低电平接VSS
推挽输出
数字输出
可输出引脚电平,高电平接VDD,低电平接VSS
复用开漏输出
数字输出
由片上外设控制,高电平为高阻态,低电平接VSS
复用推挽输出
数字输出
由片上外设控制,高电平接VDD,低电平接VSS
LED 硬件电路
LED一般采用方式1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 #include "stm32f10x.h" #include "Delay.h" int main (void ) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); while (1 ) { GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)0 ); Delay_ms(25 ); GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)1 ); Delay_ms(25 ); } }
LED流水灯 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #include "stm32f10x.h" #include "Delay.h" int main (void ) { int i = 0 ; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); while (1 ) { for (i=0 ;i<8 ;i++) { GPIO_Write(GPIOA,~(0x0001 <<i)); Delay_ms(500 ); } } }
恭喜您达成成就~——点灯大师!
蜂鸣器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 #include "stm32f10x.h" #include "Delay.h" int main (void ) { int i = 0 ; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitTypeDef GPIO_InitStructure1; GPIO_InitStructure1.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure1.GPIO_Pin = GPIO_Pin_All; GPIO_InitStructure1.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure1); while (1 ) { for (i=0 ;i<8 ;i++) { GPIO_SetBits(GPIOB, GPIO_Pin_12); Delay_ms(100 ); GPIO_Write(GPIOA,~(0x0001 <<i)); GPIO_ResetBits(GPIOB, GPIO_Pin_12); Delay_ms(100 ); } } }
按键控制LED 硬件电路
传感器模块:传感器元件(光敏电阻/热敏电阻/红外接收管等)的电阻随外界模拟量的变化而变化,通过与定值电阻分压即可得到模拟电压出,再通过电压比较器进行二值化即可得到数字电压输出
按键一般用上两种方式
左边两种接法必须要求引脚是上拉或下拉输出
右边两种接法允许引脚是浮空输入的模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 #include "stm32f10x.h" #include "Delay.h" void Key_Init (void ) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_11; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ; GPIO_Init(GPIOB, &GPIO_InitStructure); } uint8_t Key_GetNum (void ) { uint8_t KeyNum=0 ; if (!GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1)) { Delay_ms(50 ); while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1)); Delay_ms(50 ); KeyNum=1 ; } if (!GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11)) { Delay_ms(50 ); while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11)); Delay_ms(50 ); KeyNum=11 ; } return KeyNum; } #include "stm32f10x.h" void LED_Init (void ) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_SetBits(GPIOA, GPIO_Pin_1 | GPIO_Pin_2); } void LED_ON (uint16_t Pin) { GPIO_ResetBits(GPIOA, Pin ); } void LED_OFF (uint16_t Pin) { GPIO_SetBits(GPIOA, Pin ); } void LED2_TURN (void ) { if (!GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_2)) GPIO_SetBits(GPIOA, GPIO_Pin_2); else GPIO_ResetBits(GPIOA, GPIO_Pin_2); } #include "stm32f10x.h" #include "Delay.h" #include "LED.h" #include "Key.h" uint8_t Key;int main (void ) { LED_Init(); Key_Init(); while (1 ) { Key = Key_GetNum(); if (Key == 11 ) LED2_TURN(); if (Key == 1 ) LED_ON(GPIO_Pin_1); else LED_OFF(GPIO_Pin_1); Delay_ms(100 ); } }
蜂鸣器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 #include "stm32f10x.h" #include "Delay.h" #include "Buzzer.h" #include "LightSensor.h" int main (void ) { Buzzer_Init(); LightSensor_Init(); while (1 ) { if (LightSensor_Get() == 1 ) Buzzer_ON(); else Buzzer_OFF(); } } #include "stm32f10x.h" void LightSensor_Init (void ) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ; GPIO_Init(GPIOB, &GPIO_InitStructure); } uint8_t LightSensor_Get (void ) { return GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_13); } #include "stm32f10x.h" void Buzzer_Init (void ) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; GPIO_Init(GPIOB, &GPIO_InitStructure); } void Buzzer_ON (void ) { GPIO_ResetBits(GPIOB, GPIO_Pin_12); } void Buzzer_OFF (void ) { GPIO_SetBits(GPIOB, GPIO_Pin_12); } void Buzzer_TURN (void ) { if (!GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_12)) GPIO_SetBits(GPIOB, GPIO_Pin_12); else GPIO_ResetBits(GPIOB, GPIO_Pin_12); }
OLED 调试模块