本帖最后由 suncat0504 于 2022-12-8 12:15 编辑
#申请原创# @21小跑堂
本次测试完成了键盘输入、OLED显示的测试,实现任意时间(最大99小时99分钟99秒的)倒计时测试。
键盘使用TTP229构成的模块,它的适用电压支持3.3V和5.5V,使用IIC接口。OLED使用128X32点阵的,接口也是IIC的。这两个部件需要用到四个GPIO。在使用了SLCD的场合,开饭很难再另外规划出多余的GPIO,也已就是用了四个LED所在的GPIO口,刚好数据通讯也可以通过LED显示出来。
按键处理部分的代码:
#define TTP229_Port_SDA GPIOB
#define TTP229_Pin_SDA GPIO_Pin_11
#define TTP229_Port_SCL GPIOB
#define TTP229_Pin_SCL GPIO_Pin_10
#define TTP229_SDA_0() GPIO_ResetBits(TTP229_Port_SDA,TTP229_Pin_SDA)
#define TTP229_SDA_1() GPIO_SetBits(TTP229_Port_SDA,TTP229_Pin_SDA)
#define TTP229_SDA_TOGGLE() (GPIO_ReadOutputDataBit(TTP229_Port_SDA,TTP229_Pin_SDA))?(GPIO_ResetBits(TTP229_Port_SDA,TTP229_Pin_SDA)):(GPIO_SetBits(TTP229_Port_SDA,TTP229_Pin_SDA))
#define TTP229_SCL_0() GPIO_ResetBits(TTP229_Port_SCL,TTP229_Pin_SCL)
#define TTP229_SCL_1() GPIO_SetBits(TTP229_Port_SCL,TTP229_Pin_SCL)
#define TTP229_SCL_TOGGLE() (GPIO_ReadOutputDataBit(TTP229_Port_SCL,TTP229_Pin_SCL))?(GPIO_ResetBits(TTP229_Port_SCL,TTP229_Pin_SCL)):(GPIO_SetBits(TTP229_Port_SCL,TTP229_Pin_SCL))
#define TTP229_KEYCODE_1 1
#define TTP229_KEYCODE_2 2
#define TTP229_KEYCODE_3 3
#define TTP229_KEYCODE_4 4
#define TTP229_KEYCODE_5 5
#define TTP229_KEYCODE_6 6
#define TTP229_KEYCODE_7 7
#define TTP229_KEYCODE_8 8
#define TTP229_KEYCODE_9 9
#define TTP229_KEYCODE_0 10
#define TTP229_KEYCODE_Cancel 11 // 取消
#define TTP229_KEYCODE_OK 12 // 确认
//#define TTP229_KEYCODE_Left 13 // 左移
//#define TTP229_KEYCODE_Right 14 // 右移
//#define TTP229_KEYCODE_Set 15 // 设置
//#define TTP229_KEYCODE_Mode 16 // 定时器模式切换
#define TTP229_KEYCODE_T1 13 // 定时1
#define TTP229_KEYCODE_T2 14 // 定时2
#define TTP229_KEYCODE_T3 15 // 定时3
#define TTP229_KEYCODE_DT 16 // 设置日期时间
/********************************************************************
* 名称 : TTP229_ReadKey()
* 功能 : 扫描TTP229电容键盘(16按键)函数
* 触摸结果直接输出只有8个,平时输出低电平,触摸按键键后,对应输出脚为高电平
* 同时触摸按键,只有第一个生效
* 输入 : 无
* 输出 : 按键编号
***********************************************************************/
u8 TTP229_ReadKey(void) {
u8 key=0;
u8 val=0;
u8 i;
unsigned int temp=0x0000;
set_tm1638_sda_out();
TTP229_SDA_0();
delayUs(100);
TTP229_SDA_1();
delayUs(100);
set_tm1638_sda_in();
for(i=0;i<16;i++) {
TTP229_SCL_0();
delayUs(100);
TTP229_SCL_1();
delayUs(100);
if(GPIO_ReadInputDataBit(TTP229_Port_SDA, TTP229_Pin_SDA) == Bit_RESET) {
temp|=(1<<i);
}
}
for (i=0;i<16;i++) {
if ((temp & (1<<i)) > 0) {
key=i+1;
}
}
DELAY_Ms(30);
return key;
}
OLE处理中接口部分的代码:
//定义IIC从设备地址:OLED上设置的访问地址为0x78
#define IIC_SLAVE_ADDR 0x78
//--------------IIC总线引脚定义-----------------------
#define OLED_SCL_PORT GPIOC
#define OLED_SCL_PIN GPIO_Pin_0 //OLED屏IIC时钟信号
#define OLED_SDA_PORT GPIOB
#define OLED_SDA_PIN GPIO_Pin_9 //OLED屏IIC数据信号
//--------------IIC端口操作定义---------------------
#define OLED_SDA_1() GPIO_SetBits(OLED_SDA_PORT, OLED_SDA_PIN)
#define OLED_SDA_0() GPIO_ResetBits(OLED_SDA_PORT,OLED_SDA_PIN)
#define OLED_SCL_1() GPIO_SetBits(OLED_SCL_PORT, OLED_SCL_PIN)
#define OLED_SCL_0() GPIO_ResetBits(OLED_SCL_PORT,OLED_SCL_PIN)
其他处理相关代码太多,详见后面附件中工程。为了实现字符的显示(包括汉字)的显示,需要另外的工具,把用到的字符转换为点阵数据保存到文件中。为了能让OLED多显示字符,我把汉字转换为16X12的点阵。点阵数据文件格式:
计时处理中使用定时器16,通过参数设置,实现秒单位的定时中断。根据芯片资料介绍,TIM16 由一个 16 位可实时编程预分频器和一个 16 位自动重装载计数器组成,可以为用户提供便捷的计数定时功能,计数器时钟由预分频器分频得到。
// TIM16中断处理函数
void TIM16_IRQHandler(void)
{
TIM_ClearITPendingBit(TIM16, TIM_IT_Update);
ucTim16Flag++;
// 测试用代码
printf("*");
if (djsVal>0) {
// 秒数减1
djsVal--;
}
// 测试用代码
TTP229_SCL_TOGGLE(); // PB10电平翻转
}
从结构图中可以看到,计算出合理的PSC和ARR,可以从TIM16获得自己需要的信号。
为了测试精度,利用TIM16的中断处理和LED中的一个GPIO,输出一个秒信号,并用示波器测量结果。使用下面的语句:
TIM16_Init(APP_TIM_UPDATE_PERIOD - 1, SystemCoreClock / 500000);
PB10上得到的测试波形:
脉冲的周期为20ms。说明定时时长为10ms。因此如果把TIM16的时钟周期放大100倍,
TIM16_Init(APP_TIM_UPDATE_PERIOD - 1, SystemCoreClock / 5000);
定时周期将变为1秒,可以作为倒计时用的计数信号。
在主程序中周期检测键盘输入情况,按键盘上1-9的按键时,进入倒计时程序处理。此时LCD上显示00:00:00,分别对应时:分:秒,可以通过13、14调整要修改的定时时间的位置,通过1-10按键,修改数值。最大范围为99小时99分钟99秒。运行时,SLCD屏幕显示小时、分钟、秒的变化,OLED屏显示剩余的秒数。
附上测试代码:
倒计时测试.zip
(1.13 MB)
|