其实FR5739的ADC和G2553是基本一致的,就是按照手册的寄存器表,然后根据所需要实现的功能进行配置即可。。程序的配置如下:
void ADC10_Init(void) { ADC10CTL0 &= ~(ADC10ENC + ADC10ON);//DISABLE ADC CONVERSION ADC10_IO_Init(); //控制寄存器设置 ADC10CTL0 |= ADC10SHT_5 + ADC10MSC;//ADC10CLK = ADC10SHT_5,MULTIPLE SAMPLE ADC10CTL1 |= ADC10SHS_0 + ADC10SHP + ADC10SSEL_3 + ADC10CONSEQ_2;//时间触发采样,CLK = SMCLK,REPEAT-SINGLE ADC10CTL2 |= ADC10RES ;//10 BIT ADC ADC10MCTL0 |= ADC10SREF_0 +ADC10INCH_3;//VREF = VCC,SAMPLE CHANNEL = CH5 ADC10CTL0 |= ADC10ON + ADC10ENC + ADC10SC; //ENABLE ADC AND START ADC10IE |= ADC10IE0; #ifdef DMA_TRANSFER DMA_Init((uint)ADC_DMA_SA,(uint)ADC_DMA_DA,ADC_DMA_SZ);//初始化DMA,设置为重复的块搬移模式 #endif _EINT();
}
需要注意的地方在于板子的CH4接触的是NTC温度电阻,而根据电路的设计,需要使能该处的电源,
因此在配置IO的时候,除了使能IO的ADC采样通道功能外,还需要配置P2.7输出高电平。(在此自己还是一直犯了忘记开总中断 和配置IO的问题,以后得多提醒自己。。)还有就是精度的配置是通过配置ADC10CTL2中的ADC10RES来实现10位精度的。
初始化配置之后,就要开始对中断进行编写
#pragma vector=ADC10_VECTOR __interrupt void ADC10_ISP(void) { switch(__even_in_range(ADC10IV,12)) { case 2:break; case 4:break; case 6:break; case 8:break; case 10:break; case 12://CONVERSION IS CONPLETE { #ifdef DMA_TRANSFER *ADC_DMA_SA = ADC10MEM0; #else ADCRegResult = ADC10MEM0; #endif ADCOverFlag = 1; DMA1CTL |= DMAREQ; // ADC10IFG &= ~ADC10IFG0; } break; default: break; } __bic_SR_register_on_exit(LPM4_bits); }
关于中断的函数,用了__even_in_range(ADC10IV,12)的一个函数,在TI的例程里面,查询中断标志的实现大多是采用这一方式,该函数的用法是查询ADC10IV中的0-12的偶数位是否被置位,是的话返回ADC10IV的值。。这样能够提高switch的效率。
还有一个要注意的问题是假如在主函数中进入
模式,那么在除了定时器中断的其余中断函数中,需要退出该低功耗模式,否则下次将无法进入中断。。
最后就是对采样的数据进行处理,换算成电压值
void ADC10_Handle(void) { static unsigned char i = 0;//记录
if(Sys50X_ms && ADCOverFlag)//取值时间到,同时采样结束 { Sys50X_ms = 0; ADCOverFlag = 0; #ifdef DMA_TRANSFER ADCRegSum += *ADC_DMA_DA; #else ADCRegSum += ADCRegResult; #endif i++; if(i >= ADCBufLen) { i = 0; ADCRegSum = ADCRegSum>>3; ADCValue = ADCRegSum*0.003519; LCD_Write_Float(2,0,ADCValue); ADCRegSum = 0;//清除总和,重新存值 LED7_TURN; } } }
然后为了也顺便学习DMA,在进行ADC的采样值读取过程中,对DMA也进行了初始化,在程序中加入宏“DMA_TRANSFER”,可根据需要选择是否编译。。
|