TA的每日心情 | 奋斗 2015-1-22 18:04 |
---|
签到天数: 189 天 连续签到: 1 天 [LV.7]常住居民III
|
本帖最后由 nongxiaoming 于 2013-12-4 10:04 编辑
SAM4N有两种ADC,一种是12bit的,一种是10bit的。两种ADC的配置基本是一样的。因为板子上引出的ADC10和ADC11都是10bit的,所以凑合着用了,ADC的通道16读出的值就是MCU内部的温度传感器ADC值,所以这次的驱动只驱动ADC10,ADC11和ADC16,代码如下:- void ADC_Init(uint16_t adc_clk,uint8_t tracktim)
- {
- uint8_t prescal,startup,shtim;
- /*计算ADC CLK分频值*/
- prescal=SystemCoreClock/(adc_clk*2)-1;
- /*禁止外设管理控制寄存器(PMC)写保护*/
- PMC->PMC_WPMR = 0x504D4300;
- /*使能ADC和PIOC时钟*/
- PMC->PMC_PCER0 = ((1UL << ID_PIOC) |
- (1UL << ID_ADC) );
- /*使能外设管理控制寄存器(PMC)写保护*/
- PMC->PMC_WPMR = 0x504D4301;
- /*配置PC13为ADC10,PC15为ADC11*/
- PIOC->PIO_IDR=(PIO_PC13X1_AD10|PIO_PC15X1_AD11);
- PIOC->PIO_PUDR=(PIO_PC13X1_AD10|PIO_PC15X1_AD11);
- PIOC->PIO_ABCDSR[0]&=~(PIO_PC13X1_AD10|PIO_PC15X1_AD11);
- PIOC->PIO_ABCDSR[1]&=~(PIO_PC13X1_AD10|PIO_PC15X1_AD11);
- PIOC->PIO_PDR=(PIO_PC13X1_AD10|PIO_PC15X1_AD11);
- /*软件复位ADC*/
- ADC->ADC_CR=ADC_CR_SWRST;
- /*配置ADC模式*/
- ADC->ADC_MR=ADC_MR_TRGEN_DIS| //禁止硬件触发,即使用软件控制
- ADC_MR_TRGSEL_ADC_TRIG0| //使用定时器通道0的TIOA输出
- ADC_MR_LOWRES_BITS_10| //设置为10Bit模式
- ADC_MR_SLEEP_NORMAL| //设置为普通模式
- ADC_MR_PRESCAL(prescal)| //设置adc clk分频值
- ADC_MR_STARTUP_SUT8| //设置启动时间为8个adc_clk时钟周期
- ADC_MR_TRACKTIM(tracktim)|
- ADC_MR_TRANSFER(2); //这个必须为2,数据手册已注明
- /*使能通道10,通道11和通道16*/
- ADC->ADC_CHER=ADC_CHER_CH10|ADC_CHER_CH11|ADC_CHER_CH16;
- /*使能内部温度传感器*/
- ADC->ADC_TEMPMR=ADC_TEMPMR_TEMPON;
- /*开始ADC转换*/
- ADC->ADC_CR=ADC_CR_START;
- }
- void ADC_StartConvert(void)
- {
- /*开始ADC转换*/
- ADC->ADC_CR=ADC_CR_START;
- }
- void ADC_EnableChannel(uint8_t channel)
- {
- if(channel>16)
- return;
- ADC->ADC_CHER=(0x01<<channel);
- }
- void ADC_DisableChannel(uint8_t channel)
- {
- if(channel>16)
- return;
- ADC->ADC_CHDR=(0x01<<channel);
- }
- uint16_t ADC_GetConvertedData(uint8_t channel)
- {
- unsigned int data=0;
- if(channel<17){
- data = ADC->ADC_CDR[channel]&0x3ff;
- }
- return data;
- }
复制代码 对于温度来说,读出的只是一个10bit的值,需要进行转换才得到温度值。这换算公式手册并没有给出,只有官方例程提供了换算方法,如下:- /** Reference voltage for ADC,in mv. */
- #define VOLT_REF (3300)
- /** The maximal digital value */
- #define MAX_DIGITAL (1023UL)
- int16_t ADC_GetTempTemperature(void)
- {
- uint16_t adc_value;
- int16_t temp=0;
- adc_value=ADC_GetConvertedData(16);
- adc_value=adc_value* VOLT_REF / MAX_DIGITAL;
- temp = (adc_value - 1440) * 100 / 470 + 27;
- return temp;
- }
复制代码 下面是一个读取ADC值的例子:- int main(void)
- {
- systick_hw_init();
- led_hw_init();
- UART0_Init(115200);
- printf("this is a adc demo!\r\n");
- ADC_Init(4000000UL,8); //初始化adc,clk为4Mhz
- while(1){
- uint16_t adc10_value,adc11_value;
- int16_t temp=0;
- ADC_StartConvert();
- delay_ms(100);
- adc10_value=ADC_GetConvertedData(10);
- adc11_value=ADC_GetConvertedData(11);
- temp=ADC_GetTempTemperature();
- printf("ADC10:%d,ADC11:%d,Temp:%d\r\n",adc10_value,adc11_value,temp);
- PIOB->PIO_CODR=(0x01<<LED0_PIN);
- delay_ms(300);
- PIOB->PIO_SODR=(0x01<<LED0_PIN);
- delay_ms(300);
- }
- }
- 运行输出如下:
- <img src="https://www.cirmall.com/bbs/forum.php?mod=image&aid=69227&size=300x300&key=373c946ffa4cdd0dcb28c9fbf5616ac4&nocache=yes&type=fixnone" aid="attachimg_69227" alt="" border="0">
11.adc.rar
(1.07 MB, 下载次数: 10)
|
-
|