[其他ST产品] STM32F103C8T6以寄存器方式借助面包板搭建电路点亮LED流水灯详解

[复制链接]
2497|28
 楼主| 花间一壶酒sd 发表于 2023-5-30 13:17 | 显示全部楼层 |阅读模式
寄存器原理
1.什么是寄存器
寄存器是 CPU 内部用来存放数据的一些小型存储区域,用来暂时存放参与运算的数据和运算结果。其实寄存器就是一种常用的 时序逻辑电路 ,但这种时序逻辑电路只包含存储电路。 寄存器的存储电路是由锁存器或触发器构成的,因为一个锁存器或触发器能存储1位二进制数,所以由N个 锁存器 或触发器可以构成N位寄存器。寄存器是 中央处理器 内的组成部分。寄存器是有限存储容量的高速存储部件,它们可用来暂存指令、数据和位址。在计算机领域,寄存器是CPU内部的元件,包括 通用寄存器 、专用寄存器和控制寄存器。寄存器拥有非常高的读写速度,所以在寄存器之间的数据传送非常快。

2.如何访问寄存器
存放数据的寄存器是最好理解的,如果你需要读取一个数据,直接到这个寄存器所在的地方来问问他,数据是多少就行了。问寄存器这个动作,叫做访问寄存器。不同的数据会存放在不同的寄存器,例如引脚PA2与PB8的高低电平数据(1或0)肯定放在不同的寄存器里,那么怎么区分不同的寄存器呢?通过地址,不同的寄存器有不同的地址
**所以需要找到其地址,怎么找到某个寄存器的地址?查看数据手册。**在简单了解寄存器后,我们开始配置

 楼主| 花间一壶酒sd 发表于 2023-5-30 13:17 | 显示全部楼层
GPIO端口的初始化设置
1.时钟配置
想要配置时钟首先要访问其寄存器,找到地址。
(1)找到时钟使能寄存器映射基地址
时钟控制名字叫做RCC,属于AHB总线,查看数据手册如下: 8431647587026f50b.png


得出复位和时钟控制RCC的地址从0x4002 1000开始
 楼主| 花间一壶酒sd 发表于 2023-5-30 13:18 | 显示全部楼层
找到端口偏移地址以及对应端口所在位置
3525564758715dfbc3.png
手册RCC_APB2ENR,位3是IOPBEN,名字是IO端口B时钟使能,就是我们想要的。把RCC_APB2ENR的位3赋值为1,就是开启GPIOB时钟
 楼主| 花间一壶酒sd 发表于 2023-5-30 13:19 | 显示全部楼层
使能对应端口时钟
  1. //----------------APB2使能时钟寄存器 ---------------------
  2. #define RCC_APB2ENR                *((unsigned volatile int*)0x40021018)

  3.         RCC_APB2ENR|=1<<2|1<<3|1<<4;                        //APB2-GPIOA、GPIOB、GPIOC外设时钟使能       

 楼主| 花间一壶酒sd 发表于 2023-5-30 13:19 | 显示全部楼层
.端口输出寄存器配置
本次实验使用GPIOA-5、GPIOB-9、GPIOC-14 这3个引脚控制LED灯,GPIO是属于APB2的。
同理,也要访问其地址。
 楼主| 花间一壶酒sd 发表于 2023-5-30 13:20 | 显示全部楼层
找到找到GPIOX的基地址
687276475878735d84.png

结论是,
所有GPIOA相关的寄存器,都住在0x4001 0800到0x4001 0BFF范围内。
所有GPIOB相关的寄存器,都住在0x4001 0C00到0x4001 0FFF范围内。
所有GPIOC相关的寄存器,都住在0x4001 1000到0x4001 13FF范围内。
 楼主| 花间一壶酒sd 发表于 2023-5-30 13:20 | 显示全部楼层
找到端口输入寄存器的地址偏移
分别用到A4、B5、C14三个引脚。其中A4、B5属于端口配置低寄存器偏移地址为0x00,C13属于端口配置高寄存器偏移地址为0x04。
62700647587a2d9aab.png
76671647587af735b5.png
 楼主| 花间一壶酒sd 发表于 2023-5-30 13:21 | 显示全部楼层
对应引脚寄存器,基地址+偏移量
相应端口配置器GPIOA_CRL地址为GPIOA的基址+上偏移量
 楼主| 花间一壶酒sd 发表于 2023-5-30 13:21 | 显示全部楼层
  1. //----------------GPIOA配置寄存器 -----------------------
  2. #define GPIOA_CRL                *((unsigned volatile int*)0x40010800)
  3. //----------------GPIOB配置寄存器 -----------------------
  4. #define GPIOB_CRL                *((unsigned volatile int*)0x40010C00)
  5. //----------------GPIOC配置寄存器 -----------------------
  6. #define GPIOC_CRH                *((unsigned volatile int*)0x40011004)


 楼主| 花间一壶酒sd 发表于 2023-5-30 13:21 | 显示全部楼层
输入输出模式和输出速率设置
我们需要的是输出高低电平,所以要设置为输出。输出模式又有好几种输出:
6721647587da24e1a.png
 楼主| 花间一壶酒sd 发表于 2023-5-30 13:21 | 显示全部楼层
推挽输出:可以输出高,低电平,连接数字器件;推挽结构一般是指两个三极管分别受两互补信号的控制,总是在一个三极管导通的时候另一个截止。
开漏输出:输出端相当于三极管的集电极,要得到高电平状态需要上拉电阻才行,适合于做电流型的驱动,其吸收电流的能力相对强(一般20ma以内)。
开漏是需要外接上拉电阻才可以输出高电平的,这里并不适合。所以需要设置为推挽输出,没有复用,输出速度按要求设置为2Mhz
 楼主| 花间一壶酒sd 发表于 2023-5-30 13:22 | 显示全部楼层
  1. GPIOA_CRL&=0xFFF0FFFF;                //设置位 清零       
  2. GPIOA_CRL|=0x00020000;                //PA4推挽输出,把第19、18、17、16位变为0010

  3. GPIOB_CRL&=0xFF0FFFFF;                //设置位 清零       
  4. GPIOB_CRL|=0x00200000;                //PB5推挽输出,把第23、22、21、20变为0010

  5. GPIOC_CRH&=0xFF0FFFFF;                //设置位 清零       
  6. GPIOC_CRH|=0x00200000;                //PC14推挽输出,把第23、22、21、20变为0010
 楼主| 花间一壶酒sd 发表于 2023-5-30 13:22 | 显示全部楼层
三、C语言实现流水灯
1.流水灯原理
本次实验采用三个灯实现,亮灯状态用1表示,灭灯状态用0表示。
初始状态为0 0 0,
状态一为1 0 0
状态二为0 1 0
状态三为0 0 1
状态三结束后继续进入状态一,一直循环达到流水灯效果。
 楼主| 花间一壶酒sd 发表于 2023-5-30 13:22 | 显示全部楼层
2.c语言实现
(1)创建项目
点击【project】->[New…】
978766475882282d21.png
 楼主| 花间一壶酒sd 发表于 2023-5-30 13:22 | 显示全部楼层
 楼主| 花间一壶酒sd 发表于 2023-5-30 13:23 | 显示全部楼层
选择STM32F103C8开发板
19558647588380274f.png
 楼主| 花间一壶酒sd 发表于 2023-5-30 13:23 | 显示全部楼层
创建项目出现弹窗,勾选setup项和core项

5545764758845caefd.png
 楼主| 花间一壶酒sd 发表于 2023-5-30 13:23 | 显示全部楼层
在source group里创建led.c,选择【Add New Item to Group… …】
13373647588632d56a.png
 楼主| 花间一壶酒sd 发表于 2023-5-30 13:24 | 显示全部楼层
(2)写入代码
注意项目结构,使用的引脚是PA7,PB9,PC15

代码如下:
  1. #include "stm32f10x.h"
  2. //----------------APB2使能时钟寄存器 ---------------------
  3. #define RCC_APB2ENR                *((unsigned volatile int*)0x40021018)
  4. //----------------GPIOA配置寄存器 -----------------------
  5. #define GPIOA_CRL                *((unsigned volatile int*)0x40010800)
  6. #define        GPIOA_ODR                *((unsigned volatile int*)0x4001080C)
  7. //----------------GPIOB配置寄存器 -----------------------
  8. #define GPIOB_CRL                *((unsigned volatile int*)0x40010C00)
  9. #define        GPIOB_ODR                *((unsigned volatile int*)0x40010C0C)
  10. //----------------GPIOC配置寄存器 -----------------------
  11. #define GPIOC_CRH                *((unsigned volatile int*)0x40011004)
  12. #define        GPIOC_ODR                *((unsigned volatile int*)0x4001100C)


  13. //延时函数
  14. void Delay()
  15. {
  16.    u32 i=0;
  17.    for(;i<5000000;i++);
  18. }
  19. int main(void)
  20. {       
  21.         RCC_APB2ENR|=1<<2|1<<3|1<<4;                        //APB2-GPIOA、GPIOB、GPIOC外设时钟使能       
  22.        
  23.         GPIOA_CRL&=0xFFF0FFFF;                //设置位 清零       
  24.         GPIOA_CRL|=0x00020000;                //PB5推挽输出
  25.         GPIOA_ODR&=~(1<<4);                        //设置初始灯为灭
  26.        
  27.         GPIOB_CRL&=0xFF0FFFFF;                //设置位 清零       
  28.         GPIOB_CRL|=0x00200000;                //PB5推挽输出
  29.         GPIOB_ODR&=~(1<<5);                        //设置初始灯为灭
  30.          
  31.         GPIOC_CRH&=0xF0FFFFFF;                //设置位 清零       
  32.         GPIOC_CRH|=0x02000000;                //PB5推挽输出
  33.         GPIOC_ODR&=~(1<<14);                        //设置初始灯为灭               
  34.          

  35.          

  36.         while(1){
  37.                 //A灯
  38.                 GPIOA_ODR|=1<<4;                //PB5高电平
  39.                  Delay();
  40.                 GPIOA_ODR&=~(1<<4);                //PB5低电平,因为是置0,所以用按位与


  41.                
  42.                 //B灯
  43.                 GPIOB_ODR|=1<<5;                //PB5高电平
  44.                  Delay();
  45.                 GPIOB_ODR&=~(1<<5);                //PB5低电平,因为是置0,所以用按位与


  46.                
  47.                
  48.                 //C灯
  49.                 GPIOC_ODR|=1<<14;                //PB5高电平
  50.                  Delay();
  51.                 GPIOC_ODR&=~(1<<14);                //PB5低电平,因为是置0,所以用按位与


  52.                
  53.                 }
  54. }
 楼主| 花间一壶酒sd 发表于 2023-5-30 13:24 | 显示全部楼层
(3)编译运行
运行成功,要注意勾选[get hex file]
74299647588a436b1a.png
您需要登录后才可以回帖 登录 | 注册

本版积分规则

101

主题

1219

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部