四軸電池ADC監(jiān)控學(xué)習(xí)
一、硬件原理
電池供電通過兩個(gè)分壓電阻接地,STM32則在兩電阻中間通過ADC檢測(cè)電池電壓。(引腳BAT_DET)
二、ADC通道初始化
//初始化電池檢測(cè)ADC
//開啟ADC1的通道8????
//BatteryCheck---->PB0
void BatteryCheckInit()
{
??
?//先初PB0為模擬輸入
??RCC->APB2ENR|=1<<3; //使能PORTB口時(shí)鐘
??GPIOB->CRL&=0XFFFFFFF0;//PB0????anolog輸入
????//通道8????
????RCC->APB2ENR|=1<<9; //ADC1時(shí)鐘使能????
????RCC->APB2RSTR|=1<<9; //ADC1復(fù)位
????RCC->APB2RSTR&=~(1<<9);//復(fù)位結(jié)束????
????RCC->CFGR&=~(3<<14); //分頻因子清零????
????//SYSCLK/DIV2=12M ADC時(shí)鐘設(shè)置為12M,
????//
????RCC->CFGR|=2<<14; ????
????ADC1->CR1&=0XF0FFFF; //工作模式清零
????ADC1->CR1|=0<<16; //獨(dú)立工作模式
????ADC1->CR1&=~(1<<8); //非掃描模式????
????ADC1->CR2&=~(1<<1); //單次轉(zhuǎn)換模式
????ADC1->CR2&=~(7<<17);????
????ADC1->CR2|=7<<17;???? //軟件控制轉(zhuǎn)換
????ADC1->CR2|=1<<20; //使用用外部觸發(fā)(SWSTART)!!!????必須使用一個(gè)事件來觸發(fā)
????ADC1->CR2&=~(1<<11); //右對(duì)齊????
????ADC1->CR2|=1<<23; //使能溫度傳感器
????ADC1->SQR1&=~(0XF<<20);
????ADC1->SQR1&=0<<20; //1個(gè)轉(zhuǎn)換在規(guī)則序列中 也就是只轉(zhuǎn)換規(guī)則序列1 ????????????
????//設(shè)置通道1的采樣時(shí)間
????ADC1->SMPR2&=~(7<<3); //通道1采樣時(shí)間清空????
?????ADC1->SMPR2|=7<<3; //通道1 ?239.5周期,提高采樣時(shí)間可以提高精確度????
?????ADC1->SMPR1&=~(7<<18); //清除通道16原來的設(shè)置????
????ADC1->SMPR1|=7<<18; //通道16 ?239.5周期,提高采樣時(shí)間可以提高精確度????
????ADC1->CR2|=1<<0;???? //開啟AD轉(zhuǎn)換器????
????ADC1->CR2|=1<<3; //使能復(fù)位校準(zhǔn)
????while(ADC1->CR2&1<<3); //等待校準(zhǔn)結(jié)束 ????????????
??//該位由軟件設(shè)置并由硬件清除。在校準(zhǔn)寄存器被初始化后該位將被清除。 ????????
????ADC1->CR2|=1<<2; //開啟AD校準(zhǔn)????
????while(ADC1->CR2&1<<2); //等待校準(zhǔn)結(jié)束
????//該位由軟件設(shè)置以開始校準(zhǔn),并在校準(zhǔn)結(jié)束時(shí)由硬件清除
??
??Battery.BatReal = 3.95;//單位為v 電池實(shí)際電壓 ?校準(zhǔn)電壓時(shí)修改
??Battery.ADinput = 1.98;//單位為v R15和R17連接處電壓 校準(zhǔn)電壓時(shí)修改
??Battery.ADRef = 3.26;//單位為v 單片機(jī)供電電壓 ? 校準(zhǔn)電壓時(shí)修改
??Battery.Bat_K = Battery.BatReal/Battery.ADinput;//計(jì)算電壓計(jì)算系數(shù)
????Battery.overDischargeCnt = 0;
??
??printf("Batter voltage AD init ...rn");
??
}
1.配置GPIO的時(shí)鐘,模擬輸入模式
2.使能ADC時(shí)鐘,復(fù)位,寫入1結(jié)束復(fù)位。設(shè)置分頻系數(shù),為12M
3.CR1寄存器配置:設(shè)置ADC獨(dú)立模式,非掃描模式
CR2寄存器配置:A/DConverter OFF,軟件控制,使能外部事件轉(zhuǎn)換,設(shè)置右對(duì)齊,使能溫度傳感器
4.SQR1設(shè)置:配置規(guī)則通道轉(zhuǎn)換次數(shù),1次。
5.SMPR2設(shè)置通道1,SMPR1設(shè)置通道16設(shè)置取樣周期239.5
6.開啟AD轉(zhuǎn)換器,先復(fù)位校準(zhǔn),再校準(zhǔn)
三、軟件獲取ADC的值
//獲得ADC值
//ch:通道值 0~16
//返回值:轉(zhuǎn)換結(jié)果
u16 Get_Adc(u8 ch)
{
????//設(shè)置轉(zhuǎn)換序列???? ?????????
????ADC1->SQR3&=0XFFFFFFE0;//規(guī)則序列1 通道ch
????ADC1->SQR3|=ch;???????? ?????????????
????ADC1->CR2|=1<<22; //啟動(dòng)規(guī)則轉(zhuǎn)換通道
????while(!(ADC1->SR&1<<1));//等待轉(zhuǎn)換結(jié)束???? ????
????return ADC1->DR;???????? //返回adc值????
}
//獲取通道ch的轉(zhuǎn)換值,取times次,然后平均
//ch:通道編號(hào)
//times:獲取次數(shù)
//返回值:通道ch的times次轉(zhuǎn)換結(jié)果平均值
u16 Get_Adc_Average(u8 ch,u8 times)
{
????u32 temp_val=0;
????u8 t;
????for(t=0;t<times;t++)
????{
????????temp_val+=Get_Adc(ch);
????}
????return temp_val/times;
}
//得到ADC采樣內(nèi)部溫度傳感器的溫度值
//返回值3位溫度值 XXX*0.1C????
int Get_Temp(void)
{????????????????
????u16 temp_val=0;
????u8 t;
????float temperate;
????for(t=0;t<20;t++)//讀20次,取平均值
????{
????????temp_val+=Get_Adc(16);//溫度傳感器為通道16
????}
????temp_val/=20;
????temperate=(float)temp_val*(3.3/4096);//得到溫度傳感器的電壓值
????temperate=(1.43-temperate)/0.0043+25;//計(jì)算出當(dāng)前溫度值????
????temperate*=10;//擴(kuò)大十倍,使用小數(shù)點(diǎn)后一位
????return (int)temperate;????
}
//返回電池電壓AD值
int GetBatteryAD()
{
?return Get_Adc_Average(8,5);
}
感覺軟件需要封裝,獲取一次,獲取多次平均值,在獲取AD電壓。 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ?
?
? ? ? ? ? ? ?