16个触摸按键,16个8段LED数码管大电流自动刷新,STC8H4K64TL
16个触摸按键,16个8段LED数码管大电流自动涮新,STC8H4K64TL
STC8H4K64TL-45MHz-LQFP48/32, QFN48/32, 主要功能演示板, 附详细的演示程序/原理图,大家可在本贴技术讨论
1,演示了16个触摸按键输入的效果,
2,演示了 大电流自动涮新 16个8段LED数码管,简化了硬件设计,减轻了CPU的压力,简化了程序设计
===STC8H4K64TL-45MHz-LQFP48 实际可以驱动 32个8段LED数码管自动涮新
驱动8个共阴、8个共阳数码管自动扫描显示, 读取16个触摸按键, 对应16个灯.
触摸按键的读数本来是16位的, 由于使用了滤波算法, 滤波后数据为14位的.
参考电容的选取, 未按键时读数是满量程的1/3~1/2比较好, 兼顾灵敏度, 量产时又允许一定的偏差.
程序会做缓慢的0点跟踪, 所以本例不合适长按处理, 长按处理还要有别的算法.
/*------------------------------------------------------------------*/
/* --- STC MCU International Limited -------------------------------*/
/* --- STC 1T Series MCU RC Demo -----------------------------------*/
/* --- Mobile: (86)13922805190 -------------------------------------*/
/* --- Fax: 86-0513-55012956,55012947,55012969 ---------------------*/
/* --- Tel: 86-0513-55012928,55012929,55012966 ---------------------*/
/* --- Web: www.stcmcudata.com -------------------------------------*/
/* --- Web: www.stcai.com ------------------------------------------*/
/* --- BBS: www.stcaimcu.com ---------------------------------------*/
/* If you want to use the program or the program referenced in the */
/* article, please specify in which data and procedures from STC */
/*------------------------------------------------------------------*//*********************************************************/#define MAIN_Fosc 11059200L //定义主时钟#include "STC8Hxxx.h"/************* 功能说明 *************驱动8个共阴、8个共阳数码管自动扫描显示, 读取16个触摸按键, 对应16个灯.
触摸按键的读数本来是16位的, 由于使用了滤波算法, 滤波后数据为14位的.
参考电容的选取, 未按键时读数是满量程的1/3~1/2比较好, 兼顾灵敏度, 量产时又允许一定的平偏差.
程序会做缓慢的0点跟踪, 所以本例不合适长按处理, 长按处理还要有别的算法.P4.0~P4.7: 接SEG0~SEG7, 这8根SEG线跟LED连接要串联限流电阻(建议300欧姆以上).
P3.4~P3.7: 接SEG12~SEG15,这4根SEG线跟LED连接要串联限流电阻(建议300欧姆以上).
P2.0~P2.7: 接COM0~COM7P4.0 P4.1 P4.2 P4.3 P4.4 P4.5 P4.6 P4.7 P3.4 P3.5 P3.6 P3.7 SEG0 SEG1 SEG2 SEG3 SEG4 SEG5 SEG6 SEG7 SEG12 SEG13 SEG14 SEG15 A B C D E F G H LED1 LED2 LED3 LED4
P2.0-COM0
P21.-COM1
P22.-COM2
P23.-COM3
P24.-COM4
P25.-COM5
P26.-COM6
P27.-COM7bit4 bit5 bot6 bit7
COM4_DAH: K0--LED, K1-LED, K2-LED, K3-LED
COM5_DAH: K4--LED, K5-LED, K6-LED, K7-LED
COM6_DAH: K8--LED, K9-LED, K10-LED, K11-LED
COM7_DAH: K12-LED, K13-LED, K14-LED, K15-LEDP1.0-->TK0, P1.1-->TK1, P5.4-->TK2, P1.3-->TK3, P1.4-->TK4, P1.5-->TK5, P1.6-->TK6, P1.7-->TK7,
P5.0-->TK8, P5.1-->TK9, P5.2-->TK1, P5.3-->TK1, P0.0-->TK1, P0.1-->TK1, P0.2-->TK1, P0.3-->TK1,******************************************//************* 本地常量声明 **************/
#define DIS_BLACK 0x1A
#define DIS_ 0x1B/************* 本地变量声明 **************/u16 xdata TK_cnt[16]; // 键计数值
u16 xdata TK_zero[16]; // 0点读数
u16 KeyState; //键状态
u8 KeyCode; //键码 1~16
bit B_TK_Lowpass; //允许低通
bit B_ReadKeyOk; //标志已转换完成16个键
u8 TrigLimit; //触发转换限时
u8 KeyValue; //显示参数的键号, 0~15
u8 read_cnt;u8 COM4_DAH_tmp, COM5_DAH_tmp, COM6_DAH_tmp, COM7_DAH_tmp; // 16个指示灯显存/************* 本地函数声明 **************/
void delay_ms(u8 ms);
void LoadLED_A(u8 i, u8 dis);
void LoadLED_B(u8 i, u8 dis);
void ShowValue(u8 chn);
void ShowKey(void);
u8 CheckKey(u16 j);/**************** 外部函数声明和外部变量声明 *****************/u16 code T_KeyState[16] = {0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080,0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000};
// u16 code T_KeyPress[16] = {400,300,200,200, 400,300,200,200, 400,300,200,200, 400,300,200,200}; //读数无平均, 这个值是各键触摸后的变化值, 由于分布电容不同, 所以各键读数变化量不同u16 code T_KeyPress[16] = {200,150,100,100, 200,150,100,100, 200,150,100,100, 200,150,100,100}; //读数有平均, 这个值是各键触摸后的变化值, 由于分布电容不同, 所以各键读数变化量不同/**********************************************/
void main(void)
{u8 i;u16 j;P_SW2 |= 0x80; //允许访问XSFR(扩展特殊功能寄存器)// XOSCCR = 0xc0; //启动外部晶振
// while (!(XOSCCR & 1)); //等待时钟稳定
// CLKDIV = 0x00; //时钟不分频
// CKSEL = 0x01; //选择外部晶振P0M0 = 0x00;P0M1 = 0x00;P2n_push_pull(0xff); //COM0~COM7线设置为推挽输出P4n_push_pull(0xff); //SEG0~SEG7(P4.0~P4.7)线设置为推挽输出P3n_push_pull(0xf0); //SEG12~SEG15(P3.4~P3.7)线设置为推挽输出P2DR = 0x00; //COM0~COM7线设置为强电流驱动P4DR = 0x00; //SEG0~SEG7线设置为强电流驱动P3DR = 0x0f; //SEG12~SEG15线设置为强电流驱动COMEN = 0xff; //允许8个COMSEGENL = 0xff; //允许8个SEG 低字节SEGENH = 0xf0; //允许8个SEG 高字节LEDCTRL = 0x80 + (2<<4) + 0; //B7=1: ON, B5 B4: 0共阴, 1共阳, 2共阴共阳, 3保留, B2 B1 B0: 0占空比100%, 1~7占空比7/8~1/8LEDCKS = 8; //数码管COM扫描显示的主频时钟数 = 160*9*LEDCKS, 每个COM显示时间=1440*LEDCKS/fosc(MHz) us, COM扫描频率=fosc/(1440*LEDCKS *COM数).//例如 fosc = 11.0592MHz, 8个COM, LEDCKS = 8, 则每个COM显示时间=1440*8/11.0592 = 1042 us, COM扫描频率=11059200/(1440*8*8)=120Hz.//已知扫描时间t(us)计算 LEDCKS = t*fosc(MHz)/1440, 比如fosc = 24MHz, 要求1个COM扫描1ms, 则 LEDCKS = 1000*24/1440 = 16.7, 取整数17.for(i=0; i<8; i++){LoadLED_A(i,i); //共阳,显示01234567LoadLED_B(i,i+8); //共阳,显示89ABCDEF}COM4_DAH_tmp = 0;COM5_DAH_tmp = 0;COM6_DAH_tmp = 0;COM7_DAH_tmp = 0;P1n_pure_input(0xff); //Touch Key设置为高阻P5n_pure_input(0x0f);P0n_pure_input(0x0f);// TSCHEN = 0xffff; //TK0~TK15TSCHEN1 = 0xff; //TK0~TK7TSCHEN2 = 0xff; //TK8~TK15TSCFG1 = (7<<4) + 6; //开关电容工作频率 = fosc/(2*(TSCFG1[6:4]+1)), 放电时间(系统时钟周期数) 0(125) 1(250) 2(500) 3(1000) 4(2000) 5(2500) 6(5000) 7(7500) 最小3TSCFG2 = 1; //配置触摸按键控制器的内部参考电压(AVCC的分压比), 0(1/4) 1(1/2) 2(5/8) 3(3/4)
// TSCTRL = (1<<7) + (1<<6) +3; //开始扫描, B7: TSGO, B6: SINGLE, B5: TSWAIT, B4: TSWUCS, B3: TSDCEN, B2: TSWUEN, B1 B0: TSSAMP
// TSRT = 0x00; //没有LED分时扫描IE2 |= 0x80; //允许触摸按键中断EA = 1;delay_ms(50);
// B_TK_Lowpass = 0; //禁止低通滤波B_TK_Lowpass = 1; //允许低通滤波for(read_cnt=0; read_cnt<40; read_cnt++) //读40次键, 将此值作为未触摸时的0点, 要求上电时不要触摸按键{// TSCTRL = (1<<7) + (1<<6) +3; //开始扫描, 4次平均, 读数大约为无平均的一半TSCTRL = (1<<7) + (1<<6) +1; //开始扫描, 2次平均, 读数大约为无平均的一半// TSCTRL = (1<<7) + (1<<6); //开始扫描, 只转换1次, 无平均B_ReadKeyOk = 0;for(i=0; i<100; i++){if(B_ReadKeyOk) break;delay_ms(1);}}for(i=0; i<16; i++) TK_zero[i] = TK_cnt[i]; //保存0点B_TK_Lowpass = 1; //允许低通KeyState = 0;read_cnt = 0;B_ReadKeyOk = 0;KeyValue = 10;KeyCode = 0;ShowKey();while (1){delay_ms(1);if(++TrigLimit >= 100) //触发转换{TrigLimit = 0;// TSCTRL = (1<<7) + (1<<6) +3; //开始扫描, 4次平均, 读数大约为无平均的一半TSCTRL = (1<<7) + (1<<6) +1; //开始扫描, 2次平均, 读数大约为无平均的一半// TSCTRL = (1<<7) + (1<<6); //开始扫描, 只转换1次, 无平均}if(B_ReadKeyOk) // 16个键都转换完毕{B_ReadKeyOk = 0;TrigLimit = 100;ShowValue(KeyValue); //显示读数j = KeyState; //读入上一次键状态for(i=0; i<16; i++){if(TK_zero[i] > TK_cnt[i]) //计算与0点的差值{TK_zero[i]--; //缓慢0点跟随if((TK_zero[i] - TK_cnt[i]) >= T_KeyPress[i]/2) KeyState |= T_KeyState[i]; // 大于按键读数变量的1/2就是按下else if((TK_zero[i] - TK_cnt[i]) <= T_KeyPress[i]/3) KeyState &= ~T_KeyState[i]; // 小于按键读数变量的1/3就是释放}else{KeyState &= ~T_KeyState[i];if((TK_cnt[i] - TK_zero[i]) > 100) TK_zero[i] += 50; //差别很大, 则快速回0点else TK_zero[i] += 10; //差别不大, 则慢速回0点}}j = (j ^ KeyState) & KeyState; //检测键是否按下if(j != 0){KeyCode = CheckKey(j); //计算键码 1~16i = (u8)j;COM4_DAH_tmp ^= (i << 4);COM5_DAH_tmp ^= (i & 0xf0);i = (u8)(j >> 8);COM6_DAH_tmp ^= (i << 4);COM7_DAH_tmp ^= (i & 0xf0);COM4_DAH = COM4_DAH_tmp;COM5_DAH = COM5_DAH_tmp;COM6_DAH = COM6_DAH_tmp;COM7_DAH = COM7_DAH_tmp;ShowKey();if(KeyCode == 15){KeyValue--; //显示数值的键号-1KeyValue &= 0x0f;ShowValue(KeyValue); //显示读数}if(KeyCode == 16){KeyValue++; //显示数值的键号+1KeyValue &= 0x0f;ShowValue(KeyValue); //显示读数}}}}
}
/**********************************************/void delay_ms(u8 ms)
{u16 i;do{i = MAIN_Fosc / 10000;while(--i) ;}while(--ms);
}u8 code T_LED_CODE[]={ //标准字库
//代码 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F
//显示字符 0 1 2 3 4 5 6 7 8 9 A B C D E F0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,//代码 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1A 0x1B 0x1C 0x1D 0x1E 0x1F
//显示字符 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 空 -0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x00,0x40};/********************************************************/
//共阴数码管字库导入, i为LED位置0~15, dis为要显示的代码 0~9, A~F, 1.~9., 空
void LoadLED_A(u8 i, u8 dis)
{u8 xdata *px;px = &COM0_DCL + 7 - i; //PCB布局低位数码管在右边, 所以用(7-i)反一下*px = T_LED_CODE[dis];
}/********************************************************/
//共阳数码管字库导入, i为LED位置0~15, dis为要显示的代码 0~9, A~F, 1.~9., 空
void LoadLED_B(u8 i, u8 dis)
{u8 xdata *px;px = &COM0_DAL + 7 - i; //PCB布局低位数码管在右边, 所以用(7-i)反一下*px = T_LED_CODE[dis];
}/**************** 显示一个键的键号 读数 0点 ****************************************/
void ShowValue(u8 chn)
{u16 j;//共阴
// LoadLED_A(0, DIS_BLACK);
// LoadLED_A(1, DIS_BLACK);
// LoadLED_A(2, DIS_BLACK);LoadLED_A(3, DIS_BLACK);LoadLED_A(4, chn/10);LoadLED_A(5, chn%10);LoadLED_A(6, DIS_BLACK);j = TK_cnt[chn]; //按键读数LoadLED_A(7, j /1000);//共阳LoadLED_B(0, (j % 1000)/100);LoadLED_B(1, (j % 100)/10);LoadLED_B(2, j%10);LoadLED_B(3, DIS_BLACK);j = TK_zero[chn]; //0点读数LoadLED_B(4, j /1000);LoadLED_B(5,(j % 1000)/100);LoadLED_B(6,(j % 100)/10);LoadLED_B(7, j % 10);
}/****************** 显示一个键码 **************************************/
void ShowKey(void)
{u8 i;i = KeyCode;if(i == 0){LoadLED_A(0, DIS_); //共阴LoadLED_A(1, DIS_); //共阴}else{i--;LoadLED_A(0, i/10); //共阴LoadLED_A(1, i%10); //共阴}LoadLED_A(2, DIS_BLACK);
}/****************** 检测 计算键码 **************************************/
u8 CheckKey(u16 j)
{u8 i;if(j == 0) return 0; //无键按下for(i=0; i<16; i++){if(j & 0x0001) break;j >>= 1;}return (i+1); //键码1~16
}u8 isr_index;void AUXR_ISR(void) interrupt 13
{u8 j;switch(isr_index){case 32: //0103H 波形发生器5 中断入口//用户中断处理代码break;case 33: //010BH 波形发生器异常2 中断入口//用户中断处理代码break;case 34: //0113H 波形发生器异常4 中断入口//用户中断处理代码break;case 35: //011BH 触摸按键 中断入口//用户中断处理代码j = TSSTA2;if(j & 0x40) //数据溢出, 错误处理(略){TSSTA2 |= 0x40; //写1清零}if(j & 0x80) //扫描完成{j &= 0x0f;TSSTA2 |= 0x80; //写1清零if(!B_TK_Lowpass) TK_cnt[j] = TSDAT/4; //保存某个通道的读数 无低通滤波else TK_cnt[j] = ((TK_cnt[j] * 3)>>2) + TSDAT/16; //保存某个通道的读数 低通滤波if(j == 15) B_ReadKeyOk = 1; //读完一次循环}break;case 36: //0123H RTC 中断入口//用户中断处理代码break;case 37: //012BH P0口中断入口//用户中断处理代码break;case 38: //0133H P1口中断入口//用户中断处理代码break;case 39: //013BH P2口中断入口//用户中断处理代码break;case 40: //0143H P3口中断入口//用户中断处理代码break;case 41: //014BH P4口中断入口//用户中断处理代码break;case 42: //0153H P5口中断入口//用户中断处理代码break;case 43: //015BH P6口中断入口//用户中断处理代码break;case 44: //0163H P7口中断入口//用户中断处理代码break;case 45: //016BH P8口中断入口//用户中断处理代码break;case 46: //0173H P9口中断入口//用户中断处理代码break;default:break;}
}
16个触摸按键,16个8段LED数码管大电流自动刷新,STC8H4K64TL相关推荐
- avr单片机led数码管六位动态显示时分秒c语言程序,AVR单片机控制8段LED数码管同时显示 - AVR单片机8位数码管显示的程序实现(两种方法介绍)...
AVR单片机控制8段LED数码管同时显示 这是一个简单的供单片机入门学习者练习用的8段LED数码管控制汇编程序,控制一个两位的数码管同时显示字符(动态刷新).用AVR- Studio-4 开发,在AV ...
- Android模拟7段LED数码管文字显示,光标定位
效果如图 实现步骤 1.下载digital-7.ttf文件,直接百度搜索,下载,网上很多.下载下来之后,放到Android工程目录中assets/fonts目录中. 2.LedTextView.jav ...
- LED数码管的识别及检测方法
1. LED数码管介绍 LED数码管也称半导体数码管,它是将若干发光二极管按一定图形排列并封装在一起的最常用的数码显示器件之一.LED数码管种类很多,品种五花八门,这里仅向初学者介绍最常用的小型&qu ...
- 嵌入式硬件入门——LED数码管(工作原理+静态驱动)
LED数码管是一种半导体发光器件,其基本单元是发光二极管(LED) 文章目录 数码管介绍 1.数码管的分类 2.数码管内部构造及原理 数码管硬件知识 1.数码管电压与电流 2.数码管典型电路 数码管的 ...
- avr单片机led数码管六位动态显示时分秒c语言程序,AVR单片机8位数码管显示的程序实现(两种方法介绍)...
描述 本文为大家介绍两个AVR单片机8位数码管显示的程序实现. AVR单片机595驱动8位数码管的显示的电路实现 主程序代码 #include > #include //GCC中的延时函数头文件 ...
- 七段LED数码管显示译码器设计
包含按键输入并显示模块,输入为四位16进制信号,同步在led数码管显示,如果没有输入,则自动脉冲计数 module led(comscan,clr,k,kon,kc,o,comscanout); in ...
- 如何巧妙使用7段码数码管?
数码管 在开发上位机UI界面时,我们常常会希望数值可以以7段数码管的形式呈现. 关于7段数码管,最早接触应该是学习单片机的时候,它可以将数字或者字母以7段字符来呈现,所以有时候也叫7段LED数码管显示 ...
- 单片机控制LED数码管的显示
首先我们说说LED数码管的显示原理. LED数码管是常见的显示器件.LED数码管为"8"字形的,其计8段(包括小数点段在内)或7段(不包括小数点段),每一段对应一个发光二极管,有共 ...
- 利用10位AD转换器 及 LED 数码管,实现由AD转换器采集温度,并用数码管显示。温度超出一定范围,LED 指示灯闪烁报警。(主要分析进制16进制转换10进制,并用数码管显示问题)
** 题目: ** 利用原有的电路 AD 及 LED 数码管显示等例子,进行整合.实现由 AD转换器采集温度(用可调电阻模拟),温度在数码管上显示.当温度超出一定范围,用 LED 指示灯进行闪烁报警. ...
最新文章
- 使用7zip压解各种文件的经常使用命令
- php ajax城市联动,php+ajax 城市联动
- spark大数据基础概念
- REVERSE-PRACTICE-BUUCTF-11
- django 1.8 官方文档翻译:7-3 Django管理文档生成器
- 使用truffle 创建代币合约 使用ganache部署私有链 以及使用Atom 进行合约代码开发
- sqlyog怎么查找表_VBA代码解决方案第58讲:在VBA中查找指定工作表的实用方法
- RHEL6_yum本地源配置
- SonarQube代码质量管理平台 的安装、配置与使用
- linux 字幕制作工具,Arctime可视化字幕编辑器–做字幕从未如此简单
- centos7.1 修改selinux相关机制后出现开机失败,报错faild to load selinux policy freezing
- 单片机驱动SD3077时钟芯片
- SD卡pin引脚说明及PCB layout指导
- 做网站SEO优化每天都做什么
- Android3d结构光,3D结构光首功+Find+X成首款刷脸支付安卓机
- 服务器被入侵当做挖矿肉鸡
- arduino花盆含水量_Arduino教程┃模拟土壤湿度传感器的介绍
- ubuntu18.04安装谷歌浏览器
- 谷歌插件blazemeter添加到扩展程序时提示文件缺失不可读取问题解决
- c语言x21是什么意思,vivo X21是什么接口_vivo X21充电接口是什么-太平洋IT百科
热门文章
- UML 部署图 deployment diagram
- transform不生效
- 关于多端能力服务统一,我有话要说...
- android获取QQ昵称,Auto.js Pro获取QQ附近的人资料页用户昵称
- 基于JSP+Servlet+MySQL+Css+Ajax的在线网上电子图书商城
- PostgreSQL数据库中的角色(Role)、用户(User)、模式(Schema)
- 捕鱼达人单机版 3D捕鱼达人 免费捕鱼达人 无限金币
- 作为一名程序员的情感语句
- MSSQL 数据库被标记为SUSPECT状态,如何恢复?
- linux下配置nginx+keepalived高可用的各种问题以及解决办法