10×10LED矩阵的扫描点亮

最近写了一个简单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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值