使用STC15W408AS的ADC做的电容感应触摸键
#include #include #define MAIN_Fosc 24000000UL //定义主时钟 typedef unsigned char u8; typedef unsigned int u16; typedef unsigned long u32; #define Timer0_Reload (65536UL -(MAIN_Fosc / 600000)) //Timer 0 重装值, 对应300KHZ sfr P1ASF = 0x9D; //只写,模拟输入选择 sfr ADC_CONTR = 0xBC; //带AD系列 sfr ADC_RES = 0xBD; //带AD系列 sfr ADC_RESL = 0xBE; //带AD系列 sfr AUXR = 0x8E; sfr AUXR2 = 0x8F; sfr P1M1 = 0x91; // sfr P1M0 = 0x92; // sfr P0M1 = 0x93; // sfr P0M0 = 0x94; // sfr P2M1 = 0x95; // sfr P2M0 = 0x96; // sfr P3M1 = 0xB1; // sfr P3M0 = 0xB2; // sfr P4M1 = 0xB3; // sfr P4M0 = 0xB4; // sfr P5M1 = 0xC9; // sfr P5M0 = 0xCA; // sfr P6M1 = 0xCB; // sfr P6M0 = 0xCC; // sfr P7M1 = 0xE1; sfr P7M0 = 0xE2; #define TOUCH_CHANNEL 8 //ADC通道数 #define ADC_90T (3<<5) //ADC时间 90T #define ADC_180T (2<<5) //ADC时间 180T #define ADC_360T (1<<5) //ADC时间 360T #define ADC_540T 0 //ADC时间 540T #define ADC_FLAG (1<<4) //软件清0 #define ADC_START (1<<3) //自动清0 sbit P_LED7 = P2^7; sbit P_LED6 = P2^6; sbit P_LED5 = P2^5; sbit P_LED4 = P2^4; sbit P_LED3 = P2^3; sbit P_LED2 = P2^2; sbit P_LED1 = P2^1; sbit P_LED0 = P2^0; u16 idata adc[TOUCH_CHANNEL]; //当前ADC值 u16 idata adc_prev[TOUCH_CHANNEL]; //上一个ADC值 u16 idata TouchZero[TOUCH_CHANNEL]; //0点ADC值 u8 idata TouchZeroCnt[TOUCH_CHANNEL]; //0点自动跟踪计数 u8 cnt_250ms; void delay_ms(u8 ms); void ADC_init(void); u16 Get_ADC10bitResult(u8 channel); void AutoZero(void); u8 check_adc(u8 index); void ShowLED(void); void main(void) { u8 i; P0M1 = 0; P0M0 = 0; //设置为准双向口 P1M1 = 0; P1M0 = 0; //设置为准双向口 P2M1 = 0; P2M0 = 0; //设置为准双向口 P3M1 = 0; P3M0 = 0; //设置为准双向口 P4M1 = 0; P4M0 = 0; //设置为准双向口 P5M1 = 0; P5M0 = 0; //设置为准双向口 P6M1 = 0; P6M0 = 0; //设置为准双向口 P7M1 = 0; P7M0 = 0; //设置为准双向口 delay_ms(50); ET0 = 0; //初始化Timer0输出一个300KHZ时钟 TR0 = 0; AUXR |= 0x80; //Timer0 set as 1T mode AUXR2 |= 0x01; //允许输出时钟 TMOD = 0; //Timer0 set as Timer, 16 bits Auto Reload. TH0 = (u8)(Timer0_Reload >> 8); TL0 = (u8)Timer0_Reload; TR0 = 1; ADC_init(); //ADC初始化 delay_ms(50); //延时50ms for(i=0; i adc_prev[i] = 1023; TouchZero[i] = 1023; TouchZeroCnt[i] = 0; } cnt_250ms = 0; while (1) { delay_ms(50); //每隔50ms处理一次按键 ShowLED(); if(++cnt_250ms >= 5) { cnt_250ms = 0; AutoZero(); //每隔250ms处理一次0点自动跟踪 } } } void delay_ms(u8 ms) { unsigned int i; do{ i = MAIN_Fosc / 13000; while(--i) ; }while(--ms); } void ADC_init(void) { P1ASF = 0xff; //8路ADC ADC_CONTR = 0x80; //允许ADC } u16 Get_ADC10bitResult(u8 channel) //channel = 0~7 { ADC_RES = 0; ADC_RESL = 0; ADC_CONTR = 0x80 | ADC_90T | ADC_START | channel; //触发ADC _nop_(); _nop_(); _nop_(); _nop_(); while((ADC_CONTR & ADC_FLAG) == 0) ; //等待ADC转换结束 ADC_CONTR = 0x80; //清除标志 return(((u16)ADC_RES << 2) | ((u16)ADC_RESL & 3)); //返回ADC结果 } void AutoZero(void) //250ms调用一次 这是使用相邻2个采样的差的绝对值之和来检测。 { u8 i; u16 j,k; for(i=0; i j = adc[i]; k = j - adc_prev[i]; //减前一个读数 F0 = 0; //按下 if(k & 0x8000) F0 = 1, k = 0 - k; //释放 求出两次采样的差值 if(k >= 20) //变化比较大 { TouchZeroCnt[i] = 0; //如果变化比较大,则清0计数器 if(F0) TouchZero[i] = j; //如果是释放,并且变化比较大,则直接替代 } else //变化比较小,则蠕动,自动0点跟踪 { if(++TouchZeroCnt[i] >= 20) //连续检测到小变化20次/4 = 5秒. { TouchZeroCnt[i] = 0; TouchZero[i] = adc_prev[i]; //变化缓慢的值作为0点 } } adc_prev[i] = j; //保存这一次的采样值 } } u8 check_adc(u8 index) //判断键按下或释放,有回差控制 { u16 delta; adc[index] = 1023 - Get_ADC10bitResult(index); //获取ADC值, 转成按下键, ADC值增加 if(adc[index] < TouchZero[index]) return 0; //比0点还小的值,则认为是键释放 delta = adc[index] - TouchZero[index]; if(delta >= 40) return 1; //键按下 if(delta <= 20) return 0; //键释放 return 2; //保持原状态 } void ShowLED(void) { u8 i; i = check_adc(0); if(i == 0) P_LED0 = 1; //指示灯灭 if(i == 1) P_LED0 = 0; //指示灯亮 i = check_adc(1); if(i == 0) P_LED1 = 1; //指示灯灭 if(i == 1) P_LED1 = 0; //指示灯亮 i = check_adc(2); if(i == 0) P_LED2 = 1; //指示灯灭 if(i == 1) P_LED2 = 0; //指示灯亮 i = check_adc(3); if(i == 0) P_LED3 = 1; //指示灯灭 if(i == 1) P_LED3 = 0; //指示灯亮 i = check_adc(4); if(i == 0) P_LED4 = 1; //指示灯灭 if(i == 1) P_LED4 = 0; //指示灯亮 i = check_adc(5); if(i == 0) P_LED5 = 1; //指示灯灭 if(i == 1) P_LED5 = 0; //指示灯亮 i = check_adc(6); if(i == 0) P_LED6 = 1; //指示灯灭 if(i == 1) P_LED6 = 0; //指示灯亮 i = check_adc(7); if(i == 0) P_LED7 = 1; //指示灯灭 if(i == 1) P_LED7 = 0; //指示灯亮 }
上一篇:用AT89C51单片机显示倒计时程序
下一篇:用汇编语言做一个看门狗测试
推荐阅读最新更新时间:2024-11-17 00:35
推荐帖子
- EPSON TSP700 打印位置设置的问题
- 我在用EPSONTSP700的ESC\\POS指令编程时只要碰到打印位置设置的指令就出不来,不是打印出奇怪字符就是没效果,比如在页模式下打印区域的设置就老出不来,很是郁闷。请哪位做过的高手给我提示一二,最好能给个例子,不胜感激!!!!EPSONTSP700打印位置设置的问题是star的tsp700对,就是这个,好长时间了,问题就是解决不了,能指导一下吗?
- lixin811013 嵌入式系统
- 【DSP】TMS320F28035 ADC例程(ePWM+中断)
- #includeDSP28x_Project.hinterruptvoidadc_isr(void);Uint16ConversionCount;Uint16Voltage1;Uint16Voltage2;main(){InitSysCtrl();DINT;InitPieCtrl();IER=0x0000;IFR=0x0000;InitPieVectTable();EALLOW;PieVectTable.ADC
- Aguilera DSP 与 ARM 处理器
- 【SC8905 EVM测评】+交作业啦
- 作业交的很勤快,果然我是一个好学生,哈哈哈,今天把SC8905EVM的作业交上来吧,不得不说SC8905EVM非常容易上手,这也看得出,南芯对客户的周到服务,在此深表感谢。社区和南芯留的作业如图所示:看这个作业属实非常简单,既然简单,那就上手去做吧。首先把官方提供的I2C工具接入到电脑之中,win10的话不会自动去安装驱动,需要去设备管理器中找到有问题的驱动,选择自动去更新和安装;安装完成的样子如上图所示。接下来打开软件,并且把设备都接好,5V电源给BAT端,该端当
- yangjiaxu 国产芯片交流
- 请教: omap 138 中LCD如何横屏转竖屏
- 请教:omap138中LCD如何横屏转竖屏请教:omap138中LCD如何横屏转竖屏
- denglin 嵌入式系统
- 兆易GD32307E-START开发板推荐
- 兆易GD32307E-START开发板搭载GD32ARMCortex-M4微控制器主流芯片GD32F307。也是刚刚举办过的兆易杯研究生电子设计竞赛的指定开发板之一。其中主芯片GD32F307主要特性 Cortex-M4内核@120MHz 支持软硬件DSP指令 闪存执行为零等待状态 内置256KB至3072KB闪存 内置48KB至96KBSRAM EXMC接口支持外部SDRAM 高达5个UART
- okhxyyo 国产芯片交流
- gprs模块如何打电话??
- 嵌入式开发板2410的串口和wavecome的q2403a相连,手法短信已经没问题,现在想搞接打电话,不知从何下手,望大家指点.谢谢gprs模块如何打电话??这个是“非技术”啊?发错版块了吧。友情Up!
- felixty 嵌入式系统
设计资源 培训 开发板 精华推荐
- SC8902A 2S锂电池充放电
- MIKROE-3486,用于 Kinetis MK24FN256VDC12 的 MCU 卡
- 超级电容均压
- TCR5SB24A、150mA、2.4V 输出电压 CMOS 低压降稳压器的典型应用
- TCR2EN15、200mA、1.5V 输出电压 CMOS 低压降稳压器的典型应用
- NCP1729 具有高电流能力的线路和负载调节负输出电压的典型应用
- 【物联网】鸿蒙智能WIFI开关+4212046A
- fm11nc08
- KSZ8463MLI-EVAL,KSZ8463 IEEE 1588 精确时间协议 (PTP) 启用开关 IC 的评估套件功能
- 采用较低值设置电阻器的 LT3089IR 线性稳压器的典型应用电路