1.STM32CubeMX的配置
将PC8-PC15设置为GPIO_Output模式,将PD2也设置为GPIO_Output模式。
通过原理图知,LED(PC8-PC15)低电平有效,锁存器(PD2)高电平有效。
初始化时我将LED设置为高电平,熄灭状态,锁存器设置为高电平不锁存状态。
2.生成文件,打开Keil5,实现一个跑马灯
(1)HAL_Delay()
代码如下
while (1)
{
/* USER CODE END WHILE */
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_8);
HAL_Delay(50);
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_8);
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_9);
HAL_Delay(50);
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_9);
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_10);
HAL_Delay(50);
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_10);
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_11);
HAL_Delay(50);
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_11);
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_12);
HAL_Delay(50);
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_12);
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
HAL_Delay(50);
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_14);
HAL_Delay(50);
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_14);
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_15);
HAL_Delay(50);
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_15);
HAL_Delay(50);
/* USER CODE BEGIN 3 */
}
在while循环中添加如下代码
HAL_GPIO_TogglePin()函数用于反转引脚电平
HAL_Delay()函数用于延迟,单位为1ms,与嘀嗒定时器有关
当使用LCD的时候,TogglePin函数不能使用,原因是无法保存之前LED的状态,但是WritePin函数还可以使用
(2)寄存器
根据编程手册可知,GPIOx——ODR寄存器对应着输出的值,修改要以十六位形式操作
代码如下
uint8_t i = 0;
uint32_t LED= 0XFFFFFFFF;
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
for(i=0;i<8;i++)
{
LED = ((0XFFFFFEFF<<i)|(0XFFFFFEFF>>(32-i)));
GPIOC->ODR = 0X0000FFFF&LED;
HAL_Delay(50);
}
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
主要的部分就是移位操作以及与和或
(3)定时器
由手册可以看出TIM6,TIM7挂载在APB1线上
配置APB1频率为80MHz
打开定时器6的中断以及配置预分频值和计数值,打开自动装载,将频率设置为1ms
首先在初始化过程中开启定时器中断
HAL_TIM_Base_Start_IT(&htim1);
之后编写中断回调函数,内容与嘀嗒定时器内容相同
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim == &htim1)
{
if(++led_count==1000)
{
led_count=0;
led_flag=1;
}
}
}
3.题目经常要求达到某种要求后一秒钟(或一定时长)翻转一次LED灯,我采用嘀嗒定时器的方法
首先编写在嘀嗒定时器中的计时函数,因为是1ms中断一次,所以需要计数1000次。
void TIME()
{
if(++led_count==1000){led_count=0;led_flag=1;}
}
因为LCD干扰的缘故,每次操作LED之前都需要将其他不用的设置为灭状态,控制LED1的代码如下
void LED1_Control()
{
if(led_flag==1)
{
led_flag=0;
if(led_state%2==0)
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
else
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
led_state++;
}
}
最后还需要将运行代码放到主函数的循环当中去,如果要在某种情况下执行的话还需要在LED1_Control函数的最开始加一个if判断。
void Task_List()
{
LED1_Control();
}
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
Task_List();
}