一:AI8051的ADC知识分享:
Ai8051U 系列单片机内部集成了一个 12 位高速 AD 转换器。ADC的时钟频率为系统频率2分频再经过用户设置的分频系数进行再次分频(ADC的时钟频率范围为SYSck/2/1~SYSc1k/2/16)。
ADC转换结果的数据格式有两种:左对齐和右对齐。可方便用户程序进行读取和引用。
注意:ADC 的第 15 通道是专门测量内部 1.19V 参考信号源的通道,参考信号源值出厂时校准为1.19V,由于制造误差以及测量误差,导致实际的内部参考信号源相比 1.19V,大约有士1%的误差。如果用户需要知道每一颗芯片的准确内部参考信号源值,可外接精准参考信号源,然后利用 ADC 的第 15通道进行测量标定。

二:采集ADC的按键值的原理图如下所示:

三:软件代码如下所示:
3.1 读取ADC代码如下所示:
u16 Get_ADC12bitResult(u8 channel) //channel = 0~15
{
ADC_RES = 0;
ADC_RESL = 0;
ADC_CONTR = (ADC_CONTR & 0xf0) | channel; //设置ADC转换通道
ADC_START = 1;//启动ADC转换
_nop_();
_nop_();
_nop_();
_nop_();
while(ADC_FLAG == 0); //wait for ADC finish
ADC_FLAG = 0; //清除ADC结束标志
return (((u16)ADC_RES << 8) | ADC_RESL);
}3.2 通过ADC数值,判断按键值如下所示:
#define ADC_OFFSET 64
void CalculateAdcKey(u16 adc)
{
u8 i;
u16 j;
if(adc < (256-ADC_OFFSET))
{
ADC_KeyState = 0; //键状态归0
ADC_KeyHoldCnt = 0;
}
j = 256;
for(i=1; i<=16; i++)
{
if((adc >= (j - ADC_OFFSET)) && (adc <= (j + ADC_OFFSET))) break; //判断是否在偏差范围内
j += 256;
}
ADC_KeyState3 = ADC_KeyState2;
ADC_KeyState2 = ADC_KeyState1;
if(i > 16) ADC_KeyState1 = 0; //键无效
else //键有效
{
ADC_KeyState1 = i;
if((ADC_KeyState3 == ADC_KeyState2) && (ADC_KeyState2 == ADC_KeyState1) &&
(ADC_KeyState3 > 0) && (ADC_KeyState2 > 0) && (ADC_KeyState1 > 0))
{
if(ADC_KeyState == 0) //第一次检测到
{
KeyCode = i; //保存键码
ADC_KeyState = i; //保存键状态
ADC_KeyHoldCnt = 0;
}
if(ADC_KeyState == i) //连续检测到同一键按着
{
if(++ADC_KeyHoldCnt >= 100) //按下1秒后,以10次每秒的速度Repeat Key
{
ADC_KeyHoldCnt = 90;
KeyCode = i; //保存键码
}
}
else ADC_KeyHoldCnt = 0; //按下时间计数归0
}
}
}3.3 采集到的ADC显示:
if(++cnt10ms >= 10) //10ms读一次ADC
{
cnt10ms = 0;
j = Get_ADC12bitResult(0); //参数0~15,查询方式做一次ADC, 返回值就是结果, == 4096 为错误
if(j < 4096) CalculateAdcKey(j); //计算按键
}
if(KeyCode > 0) //有键按下
{
LED8[6] = KeyCode / 10; //显示键码
LED8[7] = KeyCode % 10; //显示键码
}四:实物测试如下所示:

我要赚赏金
