野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 6849|回复: 7

[STM32入门篇] 第八课 使用寄存器点亮LED 课后作业

[复制链接]
发表于 2022-7-12 12:38:53 | 显示全部楼层 |阅读模式

入门第八课《使用寄存机点亮LED》课后作业

    在入门篇 第八节课最后的两道题,如图

    野火论坛202207121122154043..png

    1.实现GPIO其他寄存器的映射

    2.采用操作BSRR、BRR来编程,点亮LED

    顺便可以用寄存器映射的方案升级优化之前写的闪烁程序!


    存储器映射需要编写头文件:stm32f10x.h

    查看参考手册的存储器映射表(英文版p51-53 中文版p28-29)

    野火论坛202207121131576900..png

    可以看到外设首地址为0x4000 0000。


    野火论坛202207121135216277..png

    APB2总线基地址0x4001 0000,相对于起始地址的偏移量为0x1 0000。


    野火论坛202207121138261604..png

    AHB总线基地址0x4001 8000,相对于起始地址的偏移量为0x1 8000。但是因为需要使用的是RCC时钟,它的首地址为0x4002 1000

    为了方便计算RCC的偏移量将其看作首地址为0x4002 0000,相对地址为0x2 0000。(写首地址0x4001 8000也没有问题,只是计算略微繁琐)

   

    根据上述条件可以写出对于外设、AHB总线、APB2总线基地址的宏定义

  1. #define PERIPH_BASE        ((unsigned int)0x40000000)
  2. #define APB2PERIPH_BASE    (PERIPH_BASE + 0x10000)
  3. #define AHBPERIPH_BASE     (PERIPH_BASE + 0x20000)
复制代码
     

       野火论坛202207121148552669..png
      RCC时钟的首地址为0x4002 1000,相对于AHB基地址0x4002 0000的偏移量为0x1000。


       野火论坛202207121150247420..png

      GPIOB端口的首地址为0x4001 0C00,相对于APB2基地址0x4001 0000的偏移量为0x0C00。
      根据上述条件可以对RCC和GPIOB的基地址宏定义:
  1. #define RCC_BASE           (AHBPERIPH_BASE+0x1000)
  2. #define GPIO_BASE          (APB2PERIPH_BASE+0x0C00)
复制代码


      APB2外设时钟使能寄存器RCC_APB2ENR(英文版p70 中文版p112)

      野火论坛202207121154259177..png

    偏移量为0x18。


    野火论坛202207121200333486..png

    GPIO所以寄存器一览,Offset是偏移量,根据这张表可以开始写宏定义了。(中文版的偏移地址0x00h的“x”没了....)

  1. #define RCC_APB2ENR  *(unsigned int*)(RCC_BASE + 0x18)

  2. #define GPIO_CRL     *(unsigned int*)(GPIO_BASE + 0x00)
  3. #define GPIO_CRH     *(unsigned int*)(GPIO_BASE + 0x04)
  4. #define GPIO_IDR     *(unsigned int*)(GPIO_BASE + 0x08)
  5. #define GPIO_ODR     *(unsigned int*)(GPIO_BASE + 0x0C)
  6. #define GPIO_BSRR    *(unsigned int*)(GPIO_BASE + 0x10)
  7. #define GPIO_BRR     *(unsigned int*)(GPIO_BASE + 0x14)
  8. #define GPIO_LCKR    *(unsigned int*)(GPIO_BASE + 0x18)
复制代码
      

      整体的头文件应该长这样:(#ifndef __STM32F10X_H #define __STM32F10X_H #endif是为了防止重复引用头文件)
  1. #ifndef __STM32F10X_H
  2. #define __STM32F10X_H
  3. //用来存放STM32寄存器映射的代码

  4. //外设 peripheral

  5. #define PERIPH_BASE        ((unsigned int)0x40000000)
  6. #define APB2PERIPH_BASE    (PERIPH_BASE + 0x10000)
  7. #define AHBPERIPH_BASE     (PERIPH_BASE + 0x20000)

  8. #define RCC_BASE           (AHBPERIPH_BASE+0x1000)
  9. #define GPIO_BASE          (APB2PERIPH_BASE+0x0C00)

  10. #define RCC_APB2ENR  *(unsigned int*)(RCC_BASE + 0x18)

  11. #define GPIO_CRL     *(unsigned int*)(GPIO_BASE + 0x00)
  12. #define GPIO_CRH     *(unsigned int*)(GPIO_BASE + 0x04)
  13. #define GPIO_IDR     *(unsigned int*)(GPIO_BASE + 0x08)
  14. #define GPIO_ODR     *(unsigned int*)(GPIO_BASE + 0x0C)
  15. #define GPIO_BSRR    *(unsigned int*)(GPIO_BASE + 0x10)
  16. #define GPIO_BRR     *(unsigned int*)(GPIO_BASE + 0x14)
  17. #define GPIO_LCKR    *(unsigned int*)(GPIO_BASE + 0x18)

  18. #endif
复制代码

      之前所有的*(unsigned int*)(0x....)都可以用定义好的别名GPIO....替代了,简化了代码。

      端口位设置/清除寄存器GPIOx_BSRR作用:
       野火论坛202207121221257714..png

       野火论坛202207121222117701..png

    高16位清零,低16位 置1;如果同时设置,低16位优先级更高。


    端口位清除寄存器GPIOx_BRR作用:

    野火论坛202207121226116918..png

    和BSRR寄存器高16位一样,清零操作。

    对于LED这样的低电平有效的外设来说,应清零使能,置1禁用。

    GPIO_BRR |=(1<<color); //led使能

    GPIO_BSRR |=(1<<color);//led停止


    将第七课代码中繁琐的地址用寄存器映射替代,优化整合代码后:


红灯闪烁:

  1. #include "stm32f10x.h"

  2. #define Red 5
  3. #define Green 0
  4. #define Blue 1

  5. void delay_us(int delay_us);
  6. void delay_ms(int delay_ms);
  7. void initial(int cl);
  8. void ledBlink(int cl);

  9. int main(void)
  10. {
  11.     RCC_APB2ENR |=(1<<3);

  12.     while(1)
  13.     {
  14.         initial(Red);
  15.         ledBlink(Red);
  16.         delay_ms(100);
  17.     }
  18. }

  19. //函数体为空,目的是为了骗过编译器不报错
  20. void SystemInit(void)
  21. {}

  22. //微秒级的延时
  23. void delay_us(int delay_us)
  24. {
  25.     volatile unsigned int num;
  26.     volatile unsigned int t;

  27.     for (num = 0; num < delay_us; num++)
  28.     {
  29.         t = 11;
  30.         while (t != 0)
  31.         {
  32.             t--;
  33.         }
  34.     }
  35. }
  36. //毫秒级的延时
  37. void delay_ms(int delay_ms)
  38. {
  39.     volatile unsigned int num;
  40.     for (num = 0; num < delay_ms; num++)
  41.     {
  42.         delay_us(1000);
  43.     }
  44. }

  45. void initial(int cl)
  46. {
  47.     GPIO_CRL &=~((0x0F)<<(4*cl));
  48. }

  49. void ledBlink(int cl)
  50. {
  51.     GPIO_CRL |=(1<<(4*cl));
  52.     GPIO_BRR |=(1<<cl);
  53.     delay_ms(100);
  54.     GPIO_BSRR |=(1<<cl);
  55. }
复制代码


红蓝灯交替:


  1. #include "stm32f10x.h"

  2. #define Red 5
  3. #define Green 0
  4. #define Blue 1

  5. void delay_us(int delay_us);
  6. void delay_ms(int delay_ms);
  7. void initial(int cl);
  8. void ledBlink(int cl);

  9. int main(void)
  10. {
  11.     RCC_APB2ENR |=(1<<3);

  12.     while(1)
  13.     {
  14.         initial(Red);
  15.         ledBlink(Red);
  16.         initial(Blue);
  17.         ledBlink(Blue);
  18.     }
  19. }

  20. //函数体为空,目的是为了骗过编译器不报错
  21. void SystemInit(void)
  22. {}

  23. //微秒级的延时
  24. void delay_us(int delay_us)
  25. {
  26.     volatile unsigned int num;
  27.     volatile unsigned int t;

  28.     for (num = 0; num < delay_us; num++)
  29.     {
  30.         t = 11;
  31.         while (t != 0)
  32.         {
  33.             t--;
  34.         }
  35.     }
  36. }
  37. //毫秒级的延时
  38. void delay_ms(int delay_ms)
  39. {
  40.     volatile unsigned int num;
  41.     for (num = 0; num < delay_ms; num++)
  42.     {
  43.         delay_us(1000);
  44.     }
  45. }

  46. void initial(int cl)
  47. {
  48.     GPIO_CRL &=~((0x0F)<<(4*cl));
  49. }

  50. void ledBlink(int cl)
  51. {
  52.     GPIO_CRL |=(1<<(4*cl));
  53.     GPIO_BRR |=(1<<cl);
  54.     delay_ms(100);
  55.     GPIO_BSRR |=(1<<cl);
  56. }
复制代码
      接下来将用后面学到的知识继续进行优化。



回复

使用道具 举报

发表于 2022-7-15 17:42:46 | 显示全部楼层
这是你自己写的嘛,,好厉害呀
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-7-16 09:56:26 | 显示全部楼层
王仔小馒头 发表于 2022-7-15 17:42
这是你自己写的嘛,,好厉害呀

嘿嘿~帖子本身的话是我自己写的~内容的话是跟着火良大大的课程一边学一边做,然后把思路步骤整理汇总到的这里的。方便以后学习用
回复 支持 反对

使用道具 举报

发表于 2022-7-17 14:21:17 | 显示全部楼层
你好,请问换一种颜色的灯怎么做啊
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-7-17 15:38:19 | 显示全部楼层
陆小小 发表于 2022-7-17 14:21
你好,请问换一种颜色的灯怎么做啊

已经在我的另一个帖子下回复你了~
回复 支持 反对

使用道具 举报

发表于 2022-7-19 21:27:53 | 显示全部楼层
GCT 发表于 2022-7-17 15:38
已经在我的另一个帖子下回复你了~

嗯嗯好的!
回复 支持 反对

使用道具 举报

发表于 2022-9-27 15:21:48 | 显示全部楼层
本帖最后由 hc2213123 于 2022-9-27 15:22 编辑

大佬厉害厉害
回复 支持 反对

使用道具 举报

发表于 2023-4-12 11:55:21 | 显示全部楼层
大佬真厉害
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-5-9 12:50 , Processed in 0.032506 second(s), 26 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表