野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 7128|回复: 5

求助 关于指南者入门篇第8节作业BSRR寄存器

[复制链接]
发表于 2022-3-3 21:52:12 | 显示全部楼层 |阅读模式
BSRR看功能可以代替ODR作为GPIO的输出,但是代码里面灯是常亮的,我有点不明白是怎么回事,来论坛求助。板子是指南者STM32F103VET6。代码如下
  1. #include "stm32f10x.h"

  2. void delay(unsigned int time);

  3. int main (void)
  4. {
  5.         RCC_APB2ENR |=(1<<3);
  6.         GPIOB_CRL &=~((0xF)<<(4*0));
  7.         GPIOB_CRL |=((0x1)<<(4*0));
  8.         GPIOB_CRL &=~((0xF)<<(4*1));
  9.         GPIOB_CRL |=((0x1)<<(4*1));
  10.         GPIOB_CRL &=~((0xF)<<(4*5));
  11.         GPIOB_CRL |=((0x1)<<(4*5));
  12.        
  13.         GPIOB_BSRR &=~(1<<0);
  14.         GPIOB_BSRR |=(1<<16);
  15.         GPIOB_BSRR &=~(1<<1);
  16.         GPIOB_BSRR |=(1<<17);
  17.         GPIOB_BSRR &=~(1<<5);
  18.         GPIOB_BSRR |=(1<<21);
  19.        
  20.         /*
  21.         GPIOB_ODR |=(1<<0);
  22.         GPIOB_ODR |=(1<<1);
  23.         GPIOB_ODR &=~(1<<5);
  24.         */

  25. }


  26. /*
  27. 作业:
  28. 1.实现GPIO其他寄存器映射
  29. 2.采用操作BSRR、BRR来编程,点亮LED //失败
  30. */
  31.        
  32. void SystemInit (void)
  33. {
  34.         //函数体为空,目的使编译器不报错
  35. }

  36. void delay(unsigned int time)
  37. {
  38.         unsigned i;
  39.         while(time--)
  40.         {
  41.                 i=1000;
  42.                 while(i--);
  43.         }
  44. }

  45. //存放32寄存器映射代码
  46. //外设 perichral

  47. #define PERIPH_BASE                                         ((unsigned int)0x40000000) //外设基地址
  48. #define APB1PERIPH_BASE        PERIPH_BASE               //外设APB1基地址
  49. #define APB2PERIPH_BASE                         (PERIPH_BASE + 0x10000)    //外设APB2基地址
  50. #define AHBPERIPH_BASE                           (PERIPH_BASE + 0x20000)    //外设AHB2基地址

  51. #define RCC_BASE              (AHBPERIPH_BASE + 0x1000)  //RCC基地址
  52. #define GPIOB_BASE            (APB2PERIPH_BASE + 0x0C00) //GPIOB基地址




  53. #define RCC_APB2ENR           *(unsigned int*)(RCC_BASE + 0x18)     //RCC中APB2外设时钟使能寄存器,寄存器直接取址
  54.          
  55. #define GPIOB_CRL             *(unsigned int*)(GPIOB_BASE + 0x00)   //端口配置低寄存器
  56. #define GPIOB_CRH             *(unsigned int*)(GPIOB_BASE + 0x04)   //端口配置高寄存器
  57. #define GPIOB_ODR             *(unsigned int*)(GPIOB_BASE + 0x0C)   //端口输出寄存器
  58. #define GPIOB_BSRR            *(unsigned int*)(GPIOB_BASE + 0x10)
  59. #define GPIOB_BRR             *(unsigned int*)(GPIOB_BASE + 0x14)
复制代码


回复

使用道具 举报

发表于 2022-3-4 17:41:02 | 显示全部楼层
没看到你在主函数中加入延时,不延时的话切换的速度太快看起来就是常亮了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-3-4 19:57:02 | 显示全部楼层
一级菜鸟 发表于 2022-3-4 17:41
没看到你在主函数中加入延时,不延时的话切换的速度太快看起来就是常亮了 ...

谢谢回答。已经突然明白过来,代码就应该灯常亮,是我理解错了。
回复 支持 反对

使用道具 举报

发表于 2022-3-4 21:58:22 | 显示全部楼层
代码中你对BSRR寄存器的操作不太正确
野火论坛202203042138388087..png

建议你仔细查看参考手册中BSRR寄存器的描述,
只有对BSRR寄存器对应的位的置1操作,
才会对ODR寄存器上对应的位的状态产生影响,
这一点和对ODR的直接操作不一样
野火论坛202203042143378937..png

BSRR和ODR的关系框图
野火论坛202203042152396047..png

另外你的开发版的灯点亮,可能是因为ODR寄存器的默认值为0x00000000
你对PB0、PB1、 PB5几个GPIO引脚的控制寄存器配置CRL好后,开发板LED灯就会亮了,
你的代码中并未体现对LED IO口的有效控制
野火论坛202203042149274778..png

另外作业中使用BSRR和BRR寄存器,主要是让你了解这两个寄存器和ODR寄存器的关系
你操作这两个寄存器,对ODR寄存器对应bit位的状态的影响,而控制LED灯亮灭,就是最直观的体现
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-3-5 00:34:24 | 显示全部楼层
梦落雨深 发表于 2022-3-4 21:58
代码中你对BSRR寄存器的操作不太正确

谢谢解答。我确实是BSRR作用理解错了,习惯的认为置1会输出1,而高16位是置1输出0。现在已经明白了,代码也能成功运行。
回复 支持 反对

使用道具 举报

发表于 2022-3-25 12:24:50 | 显示全部楼层
现在写好的代码可以分享一下吗?
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-9 22:39 , Processed in 0.029311 second(s), 26 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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