用C语言写一个电容感应触摸键程序

最新更新时间:2023-01-13来源: zhihu关键字:C语言  主时钟 手机看文章 扫描二维码
随时随地手机看文章

使用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; //指示灯亮

}


关键字:C语言  主时钟 编辑:什么鱼 引用地址:用C语言写一个电容感应触摸键程序

上一篇:用AT89C51单片机显示倒计时程序
下一篇:用汇编语言做一个看门狗测试

推荐阅读

C语言写一个红外遥控发射接收程序
红外接收程序。适用于市场上用量最大的NEC编码。应用层查询 B_IR_Press标志为,则已接收到一个键码放在IR_code中, 处理完键码后, 用户程序清除B_IR_Press标志数码管左起4位显示用户码, 最右边两位显示数据, 均为十六进制.#define MAIN_Fosc 22118400L //定义主时钟#define SysTick 10000 // 次/秒, 系统滴答频率, 在4000~16000之间#include "STC15Fxxxx.H"#define DIS_DOT 0x20#define DIS_BLACK 0x10#define DIS_ 0x11#define Timer0_Relo
发表于 2023-01-30
C语言写一个LCD1602驱动显示程序
#define MAIN_Fosc 22118400L#include "STC15Fxxxx.H"sbit P_HC595_SER = P4^0;sbit P_HC595_RCLK = P5^4;sbit P_HC595_SRCLK = P4^3;u8 hour,minute,second;void DisplayRTC(void);void RTC(void);void delay_ms(u8 ms);void DisableHC595(void);void Initialize_LCD(void);void Write_AC(u8 hang,u8 lie);void Write_DIS_Data(u8 DI
发表于 2023-01-30
C语言写一个看门狗程序测试
用STC的MCU的IO方式控制74HC595驱动8位数码管。用户可以修改宏来选择时钟频率.显示效果为: 显示秒计数, 5秒后不喂狗, 等复位.#define MAIN_Fosc 22118400L //定义主时钟#include "STC15Fxxxx.H"#define DIS_DOT 0x20#define DIS_BLACK 0x10#define DIS_ 0x11#define Timer0_Reload (65536UL -(MAIN_Fosc / 1000)) //Timer 0 中断频率, 1000次/秒u8 code t_display[]={ //标准字库// 0 1 2 3 4 5 6 7
发表于 2023-01-13
C语言写一个电容感应触摸程序
使用STC15W408AS的ADC做的电容感应触摸键#include <reg52.h>#include <intrins.h>#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 重装值, 对应300KHZsfr P1ASF = 0x9D; //只写,模拟输入选择sfr ADC_CONTR = 0xBC; //带A
发表于 2023-01-13
C语言写一个跑马灯程序
#define MAIN_Fosc 22118400L //定义主时钟#include "STC15Fxxxx.H"/********* 功能说明 ***程序使用P4.7 P4.6 P1.6 P1.7 来演示跑马灯,输出低驱动。********/void delay_ms(u8 ms);/******************** 主函数 ******************/void main(void){P0M1 = 0; P0M0 = 0; //设置为准双向口P1M1 = 0; P1M0 = 0; //设置为准双向口P2M1 = 0; P2M0 = 0; //设置为准双向口P3M1 = 0; P3M0 = 0
发表于 2023-01-13
C语言写一个驱动数码管程序
/****** 本程序功能说明 *****用STC的MCU的IO方式控制74HC595驱动8位数码管。显示效果为: 数码时钟。使用Timer0的16位自动重装来产生1ms节拍,程序运行于这个节拍下, 用户修改MCU主时钟频率时,自动定时于1ms.*****/#define MAIN_Fosc 22118400L //定义主时钟#include "STC15Fxxxx.H"#define Timer0_Reload (65536UL -(MAIN_Fosc / 1000)) //Timer 0 中断频率, 1000次/秒#define DIS_DOT 0x20#define DIS_BLACK 0x10#defin
发表于 2023-01-13
小广播
设计资源 培训 开发板 精华推荐

何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2023 EEWORLD.com.cn, Inc. All rights reserved