以前寒假的时候学习过一段时间的stm32,但是很多东西其实也不理解,简单的停留在知道这个东西和会用人家的代码的阶段。于是这个暑假和社团里的同学一起,再重新学一遍。
以前寒假的时候学GPIO输出的时候也有自己尝试去做过流水灯,但就是用很简单的方法做的,像这样:
while(1)
{
GPIO_SetBits(GPIOD, GPIO_Pin_6);
GPIO_ResetBits(GPIOD, GPIO_Pin_5);
GPIO_ResetBits(GPIOD, GPIO_Pin_7);
Delay(0xffffff);
GPIO_SetBits(GPIOD, GPIO_Pin_5);
GPIO_ResetBits(GPIOD, GPIO_Pin_6);
GPIO_ResetBits(GPIOD, GPIO_Pin_7);
Delay(0xffffff);
GPIO_SetBits(GPIOD, GPIO_Pin_7);
GPIO_ResetBits(GPIOD, GPIO_Pin_5);
GPIO_ResetBits(GPIOD, GPIO_Pin_6);
Delay(0xffffff);
}
或者是用宏替换写成LED(ON)、LED(OFF)的形式,这应该是最常见的流水灯的写法了。
但是我们这次暑假学习需要完成的任务是制作由八个小灯组成的流水灯,而且要求可以实现来回跑,即正着过去,倒着回来,再正着过去、、、。如果按照刚刚所描述的方法做这个工程未免太过繁琐。
之前学习51单片机的时候,曾经做过八个小灯的流水灯,一开始便是按照传统方法让GPIO置高或者置低,如下:
while(1) {
led1 = 1;
led2 = 0;
led3 = 0;
led4 = 0;
led5 = 0;
led6 = 0;
led7 = 0;
delay();
led1 = 0;
led2 = 1;
led3 = 0;
led4 = 0;
led5 = 0;
led6 = 0;
led7 = 0;
delay();
// (下面的省略)
}
很繁琐。
然后有一个学长说:你可以尝试用位移,就是C语言中的左移或者右移运算来解决。最终完成的代码是这样的:
while(1)
{
for(i=0;i<8;i++)
{
P0=0X01<<i;
delay();
}
for(i=6;i>0;i--)
{
P0=0X01<<i;
delay();
}
}
代码量一下缩小了。
STM32简易代码
于是在用stm32做流水灯的时候我一直在想有没有什么和51一样的简单写的方法去完成这么多流水灯呢?于是我想到了位带操作(这里不对位带操作做过多介绍)。小灯GPIO的配置就不粘贴了,下面粘贴一下main函数的内容。
#include "stm32f10x.h"
#include "bsp_led.h"
#include "weidai.h"
#include "systick.h"
void zhengxiang(uint16_t min , uint16_t max);
void nixiang(uint16_t max ,uint16_t min);
int main (void)
{
uint16_t i=0;
/*LED GPIO初始化*/
LED_GPIO_Config ();
/*设置八个小灯的默认状态*/
// for(i=1;i<=8;i++)
// PAout(i) = 0;
// PEin(3) = 0;
while(1)
{
/*流水灯实现来回跑*/
zhengxiang(1,8);
nixiang(7,2);
}
/*小灯正向跑函数*/
void zhengxiang(uint16_t min ,uint16_t max)
{
uint16_t j;
for(j=min ;j<=max;j++)
{
PAout(j)=1;
delay_ms(200);
PAout(j)=0;
}
}
/*小灯逆向跑函数*/
void nixiang(uint16_t max,uint16_t min)
{
uint16_t k;
for(k=max;k>=min;k--)
{
PAout(k)=1;
delay_ms(200);
PAout(k)=0;
}
}
这样通过修改正向函数和逆向函数中传的参数便可以修改流水灯的个数,也可以较方便的改成各种类型的流水灯,较传统方法有了许多简便之处。
我这里只用了GPIOA,如果你还需要用更多的引脚,可以在正向,逆向函数中在for把A循环完之后再写for循环去遍历B,这样即实现了控制可以用简单的代码控制许许多多的灯。