最近写了一个简单API,使用单片机实现一个10×10的LED矩阵灯的花式点亮。
由于我所用的单片机的IO口资源相对比较宽裕,所以我使用了20个io口来实现这100LED灯的控制,这里就没有用到74HC595芯片来实现引脚的扩充。
所用到的硬件资源有AC7811的芯片,使用到PA0-PA9作为LED灯的片选段,PB0-PB9作为LED的引脚的单独端。大致的原理图如下所示:
由于引脚数小于我们的灯泡数,所以我们使用扫描的方式来实现这100个灯的控制。
补充一下:如果我要点亮LED1中的1号灯(0号灯)则要将PA0和PB0的引脚同时拉高。
设计思路:
封装3个API:
1.void LED_Init(void).该函数将单片机的所用到的20个引脚初始化,主要实现的功能是将引脚方向设置成输出,并且将初始值赋值为0.
2.Led_Control(uint8_t index, uint8_t status, uint8_t flag)
/**
*@brief 用于控制需要点灯的数量
*@param index 用于点灯到的位置
*@param status 控制灯的状态 1 --- 表示亮 0 --- 表示灭
*@param flag 用于选择是点亮单个(index)的灯还是0-index所有的灯
*@retval none
*/
3.void Led_Task(void) Led刷新函数。被定时器周期性调用。为了不让LED灯出现频闪,该任务调用的时间不小于2ms
以上就是Led功能函数的编写,下面就是需求的代码实现:
1.Led初始化函数
/**
*@brief LED灯的初始化
*@param 无
*@retval 无
*/
void LED_Init(void)
{
//设置LED引脚为输出
GPIOA->GPIO_CR.GPIO_CR_Byte |= 0x000003FF;
GPIOB->GPIO_CR.GPIO_CR_Byte |= 0x000003FF;
//将LED引脚初始化置0
GPIOA->GPIO_ODR.Byte &= 0xFFFFFC00;
GPIOB->GPIO_ODR.Byte &= 0xFFFFFC00;
}
2.Led状态控制(状态赋值)函数
/**
*@brief 用于控制需要点灯的数量
*@param index 用于点灯到的位置
*@param status 控制灯的状态 1 --- 表示亮 0 --- 表示灭
*@param flag 用于选择是点亮单个(index)的灯还是0-index所有的灯
*@retval none
*/
void Led_Control(uint8_t index, uint8_t status, uint8_t flag)
{
if(flag == 1) //点亮0-index所有的灯
{
uint8_t i = 0;
for(i = 0; i < index; i++)
{
data[i] = status;
}
}
else //单独点亮某个灯
{
data[index] = status;
}
}
3.LED刷新函数
void LED_TASK(void)
{
GPIOB->GPIO_ODR.Byte &= 0xFC00;
GPIOA->GPIO_ODR.Byte &= (~(0x0001) << count);
count++;
GPIOA->GPIO_ODR.Byte |= (0x0001 << (count - 1));
uint8_t i = 0;
for(i = 0; i < 10; i++)
{
if(data[(count-1)*10 + i] == 1)
{
GPIO_SetPinBits(GPIO_PB0 + i);
}
}
if(count > 10)
{
count = 0;
}
}
所用到的全局变量的定义
uint8_t count = 0;
uint16_t data[100] = {0};//用于记录点灯数据的小本子,也就是TASK执行的依据
以上就是LED相关API的驱动,下面我们写一个定时器,周期性的调用LED_TASK();
定时器周期性调用函数:
2.1定时器的初始化
void Timer_Init(void)
{
TIMER_ConfigType timerConfig1 = {0};
/* configure TIMER channel 1, enable timer */
timerConfig1.loadValue = 48000 * 4; 1ms timerout
timerConfig1.interruptEn = 1;
timerConfig1.linkMode = 0;
timerConfig1.timerEn = 1;
TIMER_SetCallback(TIMER1, TIM1_Task);
TIMER_Init(TIMER1, &timerConfig1);
}
2.2 TIM1_Task();
void TIM1_Task(uint8_t timerIndex)
{
if (TIMER_GetIntFlag(TIMER1))
{
TIMER_ClrIntFlag(TIMER1);
LED_TASK();
}
}
最后就是main函数
int main(void)
{
InitDelay();
LED_Init();
// Led_Control(78, 1, 1);
Timer_Init();
while(1)
{
uint8_t i = 0;
for(i = 0; i < 65; i++)
{
// Led_Control(99, 0, 1);
Led_Control(i, 1, 0);
mdelay(100);
}
}
}
到此,所有的模块就到此结束啦
附上工程地址:id7729/AC7811_Code: 用与存放AC7811单片的一些项目工程代码 (github.com)