本帖最后由 zhjb1 于 2014-5-2 09:01 编辑
昨天是5.1-劳动节吗,就玩了一会儿M051单片机的Time,PWM,ADC前两个主要是采用案例中的函数作些取舍完成的,个别用了寄存器,看看看Datasheet,而ADC的案例内容少,并且只有AIN0,AIN1,我想试试2,3...,这样就结合手册一起学习了一下,并且作了实验,最后的结果很理想,但很费解NuMicro的寄存器位的定义.
我得设想是,ADC0~3采用单次循环采样,而后取出数值送LCD显示采样的4个数值,不做电压转换,直接显示0~4095.
首先按照案例中的ADC0,ADC1的设置[为了好看,将顺序调整了,0连续,1连续]:
P1_MFP = P1_MFP & (~P10_AIN0_T2) | AIN0; //设置P1.0为ADC0模拟输入通道
P1_OFFD |= OFFD0; //禁止P1.0数字输入通道
P1_PMD = P1_PMD & (~Px0_PMD) | Px0_IN; //配置P1.0为输入功能
P1_MFP = P1_MFP & (~P11_AIN1_T3) | AIN1; //设置P1.1为ADC1模拟输入通道
P1_OFFD |= OFFD1; //禁止P1.1数字输入通道
P1_PMD = P1_PMD & (~Px1_PMD) | Px1_IN; //配置P1.1为输入功能
按照上述,我理解ADC2的就应该是:
P1_MFP = P1_MFP & (~P12_AIN2_T2) | AIN2; //设置P1.2为ADC2模拟输入通道
P1_OFFD |= OFFD2; //禁止P1.2数字输入通道
P1_PMD = P1_PMD & (~Px2_PMD) | Px2_IN; //配置P1.2为输入功能
结果确报P12_AIN2_T2错,我打开所有连接文件,最后在UART.C的连接文件Register_Bit.h中找到了寄存器说明,遍历没有这个寄存器定义,有的就是P12_AIN2_RXD1? 难道这个就是?结果就是ADC2的口定义,余下的就可知,见词不能识意!好在我的问题已解.
下边我们来看看寄存器操作的概念:
打开M0516的手册[因为有中文的,就用中文的]:M051寄存器配置手册_SC-LAN.pdf,6功能描述,6.11模拟数字转换(ADC)
6.11.1~6.11.3可以了解,关心硬件多看看6.11.3的图
6.11.4ADC操作步骤,有用!你可以知道ADC具有自检!有4种操作模式,并且,在改变模式或输入通道嘴还先进性ADST的清0
6.11.5列出了ADC8个只读结果寄存器存放通道0~7转换的结果;后6个可读写的A/D控制和状态寄存器.最后一个是ADC校准用的,直接永远函数即可,ADSR状态,也直接用函数定义,两个比较寄存器我不用就不看了.重点是ADCR控制寄存器和ADCHER通道使能寄存器
我的ADC初始化程序基本上用函数,主要是ADC复位,时钟选择,使能,自检,设置ADC0~3通道的I/O参数和ADC的中端使能的,并且不进行ADC转换.
另写了一段ADC通道选择和控制语句以完成ADC工作模式和通道选择以及开始1次转换,下边是寄存器的理解
ADCR-ADC控制寄存器H->0:00000000 00000000 0000 ADST DIFFEN 0 TRGEN TRGCOND7:6 TRGS5:4 ADMD3:2 ADIE ADEN
ADST=1,开始ADC转换[按照设定的转换方式],=0结束或空闲;
DIFFEN=1差分输入[01,23,45,67对];=0单端输入;本次设0
TRGE=1外部触发ADC,=0禁用;本次设0
TRGCOND7:6=00低电平,=01高电平,=10下降沿,=11上升沿;本次设00,因为禁用
TRGS5:4=00外部启动ADC,=011011无用,本次设00,因为禁用
ANMD3:2=00单次转换,=01突发转换,=10单周期扫描,11连续扫描;本次设10,启动1次扫描1周[ADC0~ADC3]
ADIE=1使能中断,=0 禁用中断;本次设1,由中断子程读取ADC转换结果送LCD显示
ADEN=1转换使能,=0 禁用;本次设1
这样ADCR就设置为:0b00000000000000000000000100001111=0x0000010F
ADCHER-ADC通道使能寄存器H->0:00000000 00000000 000000 PRESEL9:8 CHEN7 CHEN6 ... CHEN1 CHEN0
PRESEL9:8=00外部模拟,=01内部参考基准,1011保留;本次设01
CHEN7~0,Bit=1对应通道允许,=0禁止,本次设00001111,CHEN3~CHEN0为ADC
这样ADCHER设置为:0b00000000000000100010001011=0x0000088B
testADC(){
ADCHER=0x0000010F;
ADCR=0x0000088B;
ADCR |= ADST;
}
每调用一次testAdc()进行1循环的ADC转换,结果在ADC中断子程中读出,主程序送LCD显示.
体会:函数太难理解和学习,通用性会强点;寄存器看明白了操作简单快捷方便
实际上如果我有充足的时间,我还是喜欢和习惯采用写寄存器方式.实际上我得所有功能性操作都由两个模块组成:1个是初始化,比如PWMInit(),adcInit(),等;还有1个启动子程,比如startPWM(),testAdc();这些都是用寄存器方式写的子程.
以上经供大家讨论学习.
|