二、按键、灯矩阵扫描

为了做到能拍照及录像不频闪,所以选择定时器设置每250us做一次灯扫描,然后每扫完所有灯后做一次按键扫描。

一、变量设计

1、按键

共6行21列,创建一个数组,数组共6个元素,每个元素4个字节:

#define KEY_ROW 6u
#define KEY_COL	21u

u32 KeyMap[KEY_ROW];

每个元素里包含21列的IO状态,设计为从最低位开始,依次表示第1列到第21列IO状态;

2、灯光

共12COM、9SEG,创建一个结构体数组,数组共12*9=108个元素,每个元素的结构体由r、g、b三个变量组成:

#define RGB_SEG 9
#define RGB_COM 12
#define RGB_NUM (RGB_SEG*RGB_COM)

typedef struct
{
	u8 r;
	u8 g;
	u8 b;
}RGB_STRUCT;

RGB_STRUCT RGBMgr[RGB_NUM];

这里r、g、b的排列根据实际硬件排布决定,有些走线可能是gbr之类的顺序;

3、当前灯光扫描的COM索引

u8 CathodeCom@(0x00);

这里使用了强制指定地址,为了方便后面的汇编使用。

二、代码设计

1、初始化

将所有变量初始化,按键初始化0XFFFFFFFF,其余初始化为0;pwm初始化为频率20KHz以上、周期寄存器设置为255,定时器设置250us;此处就不贴代码了,硬件初始化每个芯片不一样;

2、灯光扫描

步骤:

1、关闭所有的PMOS,也就是COM的IO输出高电平;

2、COM索引指向的RGB结构体里的值赋值到PWM占空比寄存器;此时最好是能重新启动PWM。

3、打开索引指向的PMOS,索引+1,结束;

static uc8 CathodeTab[RGB_COM*3]=
{
	B(11011111),B(11111111),B(11111111),
	B(10111111),B(11111111),B(11111111),
	B(01111111),B(11111111),B(11111111),
	B(11111111),B(11111110),B(11111111),
	B(11111111),B(11111101),B(11111111),
	B(11111111),B(11111011),B(11111111),
	B(11111111),B(11110111),B(11111111),
	B(11111111),B(11101111),B(11111111),
	B(11111111),B(11011111),B(11111111),
	B(11111111),B(10111111),B(11111111),
	B(11111111),B(01111111),B(11111111),
	B(11111111),B(11111111),B(11111101),
};
void RGBMgr_Cathode(void)
{
//PWM1、PWM2输出低电平
	PWM2RLDEN = 0X55;
	PWM2EN = 0; //关闭PWM2使能
	TC1EN = 0; //关闭定时器1使能,PWM1所有已使能的模块将强制输出无效电平
//关闭COM(COM切为输入上拉,PNP此处可能需要改为输出高电平,以加快PNP关闭速度)
	OEA1 = 0;
	OEE = 0;
	OED = 0;
//更新PWM2占空比
	u8 *pDuty = &RGBMgr[M(CathodeCom,0)].r;
	PWM2_0PL = *pDuty++;
	PWM2_0NL = *pDuty++;
	PWM2_1PL = *pDuty++;
	PWM2_1NL = *pDuty++;
	PWM2_2PL = *pDuty++;
	PWM2_2NL = *pDuty++;
	
//更新PWM1占空比
	u8 *ptr = PWM1DL_BaseAddr;
	for(u8 i=0;i<PWM1_NUM;i++)
	{
		*ptr = *pDuty++;
		ptr -= 2;
	}

//COM端输出状态
	IOD &= CathodeTab[CathodeCom*3];
    IOE &= CathodeTab[CathodeCom*3 + 1];
    IOA &= CathodeTab[CathodeCom*3 + 2];
//打开定时器1、PWM2使能	
	PWM2EN = 1;
	PWM2RLDEN = 0XAA;
	TC1EN = 1;
//COM设为输出端口	
	OEA1 = 1;
	OEE = 0XFF;
	OED = 0XFF;

	if(++CathodeCom>=RGB_COM)	
	{
		CathodeCom=0;
	}
}

这段主要是利用一个const数组来改变PMOS的状态,其余大部分为硬件操作。

3、按键扫描

在灯光扫描完一轮后,做一次按键扫描,依次将每个行输出低电平,列IO做上拉输入,按键按下会读到低电平,否则为高电平;

按键矩阵扫描基本操作了,这里就不贴代码了。

4、汇编

上述的所有代码是用C写的,但由于运行时间过长,实际灯光帧数较低,在拍照或者录像都会有严重频闪,所以最终将所有的C转成了汇编,并优化了代码时间,由原来的运行时间200us缩减至25us,基本能保证在拍照以及正常录像下不频闪,由于汇编的助记符和PIC18的完全不同,所以这里就不贴出来了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值