文章目录
1、原理学习。学习和理解STM32F103系列芯片的地址映射和寄存器映射原理;了解GPIO端口的初始化设置三步骤(时钟配置、输入输出模式设置、最大速率设置)。
1.寄存器
(1)寄存器的含义
寄存器是CPU内部用来存放数据的一些小型存储区域,用来暂时存放参与运算的数据和运算结果。其实寄存器就是一种常用的时序逻辑电路,但这种时序逻辑电路只包含存储电路。寄存器的存储电路是由锁存器或触发器构成的,因为一个锁存器或触发器能存储1位二进制数,所以由N个锁存器或触发器可以构成N位寄存器。寄存器是中央处理器内的组成部分。寄存器是有限存储容量的高速存储部件,它们可用来暂存指令、数据和位址。
(2)寄存器具有的四个功能
①清除数码:将寄存器里的原有数码清除。
②接收数码:在接收脉冲作用下,将外输入数码存入寄存器中。
③存储数码:在没有新的写入脉冲来之前,寄存器能保存原有数码不变。
④输出数码:在输出脉冲作用下,才通过电路输出数码。
仅具有以上功能的寄存器称为数码寄存器;有的寄存器还具有移位功能,称为移位寄存器。
2.地址映射和寄存器映射原理
通过查看数据手册找到某个寄存器的地址。
STM32给不同的寄存器分配了不同的地址。要了解不同寄存器的地址范围需要自己查看手册。
想读取PB3引脚的电平,需要查询PB3的地址。
PB3是在GPIOB端口--------->找到GPIOB的基地址------>找到GPIOB的地址范围。
所有GPIOB相关的寄存器,地址都在0x4001 0C00到0x4001 0FFF范围内。
----->找到端口输入寄存器的地址偏移
找到存储数据的那个屋子,结论是0x4001 0C00+8 = 0x4001 0C08
------>找到知道数据的那个人
PB3的数据位于从右往左数第4位。IDR3。
经过这三步查找,我们可以做出以下结论:
PB3的输入数据位于0x4001 0C08这个地址上,这个地址上存放数据的右起第4个位就是PB3引脚对应的高低电平。
直接访问这个地址:
unsigned int *pGPIOB_IDR = (unsigned int *)0x40010C08; unsigned char PB3 = *pGPIOB_IDR & 0x8;//取出从右往左数的第4位
2、GPIO端口的初始化设置三步骤(时钟配置、输入输出模式设置、最大速率设置)
采用GPIOA、B、C三个端口。该三个端口都属于APB2总线
1.找到时钟使能寄存器映射基地址
2.找到端口偏移地址以及对应端口所在位置
3.使能对应端口时钟
//----------------APB2使能时钟寄存器 ---------------------
#define RCC_APB2ENR *((unsigned volatile int*)0x40021018)
RCC_APB2ENR|=1<<2|1<<3|1<<4; //APB2-GPIOA、GPIOB、GPIOC外设时钟使能
2.输入输出模式和输出速率设置
本次实验采用通用推挽输出模式,最高输出时钟频率2Mhz。分别用到B0、B5、A1三个引脚。其中A4、B5属于端口配置低寄存器偏移地址为0x00,C13属于端口配置高寄存器偏移地址为0x04。
1.找到GPIOx端口基地址
GPIOA、GPIOB、GPIOC配置引脚
//----------------GPIOA配置寄存器 -----------------------
#define GPIOA_CRL *((unsigned volatile int*)0x40010800)
//----------------GPIOB配置寄存器 -----------------------
#define GPIOB_CRL *((unsigned volatile int*)0x40010C00)
//----------------GPIOC配置寄存器 -----------------------
#define GPIOC_CRH *((unsigned volatile int*)0x40011004)
3.设置输出模式为推挽输出,输出速度为2Mhz
GPIOA_CRL&=0xFFF0FFFF; //设置位 清零
GPIOA_CRL|=0x00020000; //PA4推挽输出,把第19、18、17、16位变为0010
GPIOB_CRL&=0xFF0FFFFF; //设置位 清零
GPIOB_CRL|=0x00200000; //PB5推挽输出,把第23、22、21、20变为0010
GPIOC_CRH&=0xFF0FFFFF; //设置位 清零
GPIOC_CRH|=0x00200000; //PC14推挽输出,把第23、22、21、20变为0010
2、假设你手中已有 STM32最小系统核心板(STM32F103C8T6)+面板板+3只红绿蓝LED,并搭建了电路,用3个引脚上控制LED灯(最高时钟2Mhz),轮流闪烁,间隔时长1秒。
1)写出程序设计思路,包括GPIOx端口的各寄存器地址和详细参数;
1.流水灯原理
创建一个工程,勾选core项,在output中选择creat hex file
source group里创建led.c,并写入代码,注意项目结构,使用的引脚是PA1,PB0,PB5
//--------------APB2???????------------------------
#define RCC_AP2ENR *((unsigned volatile int*)0x40021018)
//----------------GPIOA????? ------------------------
#define GPIOA_CRL *((unsigned volatile int*)0x40010800)
#define GPIOA_ORD *((unsigned volatile int*)0x4001080C)
//----------------GPIOB????? ------------------------
#define GPIOB_CRH *((unsigned volatile int*)0x40010C04)
#define GPIOB_ORD *((unsigned volatile int*)0x40010C0C)
//----------------GPIOC????? ------------------------
#define GPIOC_CRH *((unsigned volatile int*)0x40011004)
#define GPIOC_ORD *((unsigned volatile int*)0x4001100C)
//-------------------???????-----------------------
void Delay_wxc( volatile unsigned int t)
{
unsigned int i;
while(t--)
for (i=0;i<800;i++);
}
//------------------------???--------------------------
int main()
{
int j=100;
RCC_AP2ENR|=1<<2; //APB2-GPIOA??????
RCC_AP2ENR|=1<<3; //APB2-GPIOB??????
RCC_AP2ENR|=1<<4; //APB2-GPIOC??????
//????????? RCC_APB2ENR|=1<<3|1<<4;
GPIOA_CRL&=0x0FFFFFFF; //??? ??
GPIOA_CRL|=0x20000000; //PA7????
GPIOA_ORD|=1<<7; //???????
GPIOB_CRH&=0xFFFFFF0F; //??? ??
GPIOB_CRH|=0x00000020; //PB9????
GPIOB_ORD|=1<<9; //???????
GPIOC_CRH&=0x0FFFFFFF; //??? ??
GPIOC_CRH|=0x30000000; //PC15????
GPIOC_ORD|=0x1<<15; //???????
while(j)
{
GPIOA_ORD=0x0<<0; //PB0???
Delay_wxc(1000000);
GPIOA_ORD=0x1<<0; //PB0???
Delay_wxc(1000000);
GPIOB_ORD=0x0<<9; //PB9???
Delay_wxc(1000000);
GPIOB_ORD=0x1<<9; //PB9???
Delay_wxc(1000000);
GPIOC_ORD=0x0<<15; //PC15???
Delay_wxc(1000000);
GPIOC_ORD=0x1<<15; //PC15???
Delay_wxc(1000000);
}
}
线路连接:USB转TTL模块和stm32f103c8t6连接
stm32f103核心板 USB TO TTL
G ------------------------------GND
PA9 ---------------------------RXD
PA10 -------------------------TXD
V3.3 --------------------------3.3V
添加驱动文件,驱动文件需要自己下载。
添加到
右击文件夹,选择Add Existing Files to Group Source Group 1。添加刚刚添加的启动文件。stratup_upstm32f10x_md.s。
build生成hex文件。
连接到电脑,打开Flymcu,上传HEX文件到stm32f103c8t6上:
烧录。插上USB To TTL,点击搜索串口。
烧录成功。
结果:(本打算交一个视频,但是剩下的时间不够视频审核了,就只能交三张截图。)
3、安装 stm32CubeMX,用cubemx完成初始化过程,采用HAL库编程实现。
1.打开stm32CubeMX,点击file,选择New Project。选择STM32F103C8
2.选择管脚PB0,PB5,PA1,设置为GPIO_output。
选择晶振High Speed Clock设置为Crystal/Ceramic Resonator
引脚自动设置为时钟
3.时钟源设置
HCLK设置为72MHz
4.配置工程文件
存储目录不能有中文
点击CodeGenerator,选择copy only the…
点击GENERATE CODE,创建工程。
5.打开工程
添加代码到main.c文件的while循环中。结果如图。
代码:`
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET);
HAL_Delay(1000);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET);
HAL_Delay(1000);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_RESET);
HAL_Delay(1000);
`
编译、烧录
结果:
4、在Keil下用软件仿真运行上面代码,并用虚拟逻辑分析仪观察 对应管脚上的输出波形(高低电平转换),看是否是1秒的周期。
1.设置仿真模式
先设置Debug模式,在Debug设置里下面两项内容进行更改:
Dialog DLL默认是DARMSTM.DLL
Parameter默认是-pSTM32F103VC
结果:
2.调试,打开逻辑分析仪
点击setup添加要观察的IO口。直接以PORTX>>X的形式输入。将Display Type设置为Bit
运行。
波形图:
参考:
https://blog.csdn.net/qq_46467126/article/details/120847240
https://blog.csdn.net/geek_monkey/article/details/86291377
https://blog.csdn.net/geek_monkey/article/details/86293880
https://blog.csdn.net/weixin_47554309/article/details/120810913
https://blog.csdn.net/qq_47281915/article/details/120812867