【蓝桥嵌入式笔记】第一个工程 HAL_01_LED_TEST

一、ODR、BSRR、BRR寄存器

1.ODR 

可读可写寄存器:既能控制管脚为高电平,也能控制管脚为低电平。

管脚对于位写1 GPIO管脚为高电平,写 0 为低电平

 

2.BSRR

只写寄存器:既能控制管脚为高电平,也能控制管脚为低电平。
对寄存器高 16bit 写1 对应管脚为低电平,对寄存器低16bit写1对应管脚为高电平。写 0 无动作。

3.​​​​​​​BRR

只写寄存器:只能改变管脚状态为低电平,对寄存器 管脚对于位写 1 相应管脚会为低电平。写 0 无动作

二、HAL库函数

1.void HAL_GPIO_TogglePin (GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin)  

翻转所选引脚的状态

void HAL_GPIO_TogglePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)

{

  /* Check the parameters */

  assert_param(IS_GPIO_PIN(GPIO_Pin)); //检查参数是否有效



  if ((GPIOx->ODR & GPIO_Pin) != 0x00u)//判断当前引脚状态与所选引脚位是否为0

  {

    GPIOx->BRR = (uint32_t)GPIO_Pin; //如果为1,则通过BRR置0

  }

  else

  {

    GPIOx->BSRR = (uint32_t)GPIO_Pin;//如果为0,则通过BSRR置1

  }

}

ODR是引脚输出值,与所选引脚进行与操作,若当前状态为1,则通过BRR置0;若当前状态为0,则通过BSRR置1。

​​​​​​​2.void HAL_GPIO_WritePin (GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)

将所选引脚置0或置1

void HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)

{

  /* Check the parameters */
  assert_param(IS_GPIO_PIN(GPIO_Pin));
  assert_param(IS_GPIO_PIN_ACTION(PinState));
  if (PinState != GPIO_PIN_RESET)
  {
    GPIOx->BSRR = (uint32_t)GPIO_Pin;
  }
  else
  {
   GPIOx->BRR = (uint32_t)GPIO_Pin;
  }
}

思考:

既然ODR 能控制管脚高低电平为什么还需要BSRRBRR寄存器?

意法半导体给的答案是

“This way, there is no risk that an IRQ occurs between the read and the modify access.”
什么意思呢?就就是你用BSRRBRR去改变管脚状态的时候,没有被中断打断的风险。也就不需要关闭中断。

ODR操作GPIO的伪代码如下:

disable_irq()
save_gpio_pin_state = read_gpio_pin_state();
save_gpio_pin_state = xxxx;
chang_gpio_pin_state(save_gpio_pin_sate);
enable_irq();

关闭中断明显会延迟或丢失一事件的捕获,所以控制GPIO的状态最好还是用BSRRBRR

​​​​​​​ 3.HAL_Delay(DELAY_TIME);

ms延时函数,弱函数,能重定义(比赛的时候直接用就可以,不必修改),参数的单位为毫秒,使用的时钟为SysTick

__weak void HAL_Delay(uint32_t Delay)

{

  uint32_t tickstart = HAL_GetTick();
  uint32_t wait = Delay;
  /* Add a freq to guarantee minimum wait */
  if (wait < HAL_MAX_DELAY)
  {
    wait += (uint32_t)(uwTickFreq);
// 查看全局变量uwTickFreq的定义,其数值为systick时钟的默认频率(1khz)
  }
  while ((HAL_GetTick() - tickstart) < wait)
  {
  }
}

__weak uint32_t HAL_GetTick(void)
{
  return uwTick;
}

三、void LED_TEST()函数

while(1){
		HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_8);
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
		HAL_Delay(DELAY_TIME);
…
}

问题一:为什么要配置PD2引脚?

如下图所示,板子引脚PD2已经与LE相连,所以需要通过对PD2的配置来对锁存器(74HC573)进行开关操控。

 

问题二:在翻转函数第一次作用之前,灯的状态是怎样的?

可以通过ODR得知灯的状态,查看ODR电后的状态(Reset value):0x0000 0000

 

补充:灯对应引脚的默认值也可以在CubeMx里面修改

问题三:锁存器有什么作用?在这个函数中是如何体现的?

锁存器能够将相连引脚的状态锁住,一旦关闭锁存器,不论引脚的状态如何改变,仍然保留的是关闭锁存器前的状态。

  1. OEH(高电平)时,无论Input(输入端D0~D7)输入何种电平状态,Output(输出端Q0~Q7))都为Z(高阻态此时芯片处于不可控状态。
  2. OEL(低电平)时,若LEH,则D(输入)与Q(输出)同时为LH(Q端的电平状态紧随着D端变化);而当LEL时,无论D为何种电平状态,Q都会保持上一次的电平(Q端电平状态将保持住LE端变化为低电平L之前端的电平状态)。

下面我们附上在开发板的74HC573原理图:

 

 

LED_TEST函数中,需要实现灯依次亮并保持到所有的灯全亮后,再依次灭掉,其中保持灯亮或灭这个状态就是通过锁存器实现的。

补充:在CubeMx创建的工程中,代码要写在对应的区域,这样能够防止重新在CubeMx中修改时,已有的代码被刷新掉

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GAG WOMEN

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值