stm8L051芯片內部的參考電壓與電源電壓有一定的關係,
這在芯片供電電壓變化的情況下,測量外部ADC電壓輸入
提供一個確定的參考電壓。這裏提前釐清下:該內部參考
電壓VREFINT 並非ADC 的參考電壓,ADC 的參考電壓依
然是VDD。即使VDD 有所波動,這個VREFINT 電壓恆定
不變,對於ADC 電路而言,它只是個測試點。
對於某固定的ADC 參考電壓情況下,所有被測電壓點的
AD轉換值與該點電壓值保持同一比例關係,換句話說,
對於ADC參考電壓固定情況下,各點的電壓與ADC值與成
線性關係。下面圖形是芯片分別在3個不同參考電壓的示意
圖,這裏參考電壓接VDD。下面三根斜線分別是VDD 爲2.8V
、3.2V、3.6V 時的AD轉換曲線示意圖。那根黃色垂直虛線是
表示內部VREFINT電壓(1.22V)所在的位置。
(圖片以及部分文字是引用網友的原話,如果需要我備註的請給我提醒一下)
剛開始的時候我是直接操作寄存器,但無奈怎樣讀測
不準,計算值同實際電源電壓差別比較大,後來不得
已才用庫函數試試。效果還可以,能測量電源的電壓,
當然stm8L芯片內部已經有一個出廠時寫好的校準值,
程序中可以讀取,這裏我只用手冊中(技術手冊中比編
程手冊說的詳細一點),的典型值1.224V。下面是相
關的代碼(參考固件庫的adc與dma例程):
#include "adc.h"
#include "led.h"
uint16_t Buffer[BUFFER_SIZE] = {0};
uint32_t Verfin = 0;//電源電壓*1000
void ADC_Config(void)
{
/* Enable ADC1 clock */
CLK_PeripheralClockConfig(CLK_Peripheral_ADC1, ENABLE);
/* Initialize and configure ADC1 */
ADC_Init(ADC1, ADC_ConversionMode_Single, ADC_Resolution_12Bit, ADC_Prescaler_1);
ADC_SamplingTimeConfig(ADC1, ADC_Group_SlowChannels, ADC_SamplingTime_24Cycles);
ADC_SamplingTimeConfig(ADC1, ADC_Group_FastChannels, ADC_SamplingTime_24Cycles);
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
ADC_VrefintCmd(ENABLE);
/* Enable ADC1 Channels 3 */
ADC_ChannelCmd(ADC1, ADC_Channel_3, ENABLE); /* connected to Potentiometer RV */
/* Enable ADC1 Channels 24 */
ADC_ChannelCmd(ADC1, ADC_Channel_Vrefint, ENABLE); /* connected to ADC_Channel_Vrefint */
}
void DMA_Config(void)
{
/* Enable DMA1 clock */
CLK_PeripheralClockConfig(CLK_Peripheral_DMA1, ENABLE);
/* Connect ADC to DMA channel 0 */
SYSCFG_REMAPDMAChannelConfig(REMAP_DMA1Channel_ADC1ToChannel0);//ADC通道要remap
//BUFFER_SIZE
DMA_Init(DMA1_Channel0, BUFFER_ADDRESS,
ADC1_DR_ADDRESS,
BUFFER_SIZE,
DMA_DIR_PeripheralToMemory,
DMA_Mode_Circular,
DMA_MemoryIncMode_Inc,
DMA_Priority_High,
DMA_MemoryDataSize_HalfWord);
/* DMA Channel0 enable */
DMA_Cmd(DMA1_Channel0, ENABLE);
/* Enable DMA1 channel0 Transfer complete interrupt */
DMA_ITConfig(DMA1_Channel0, DMA_ITx_TC, ENABLE);
/* DMA enable */
DMA_GlobalCmd(ENABLE);
ADC_DMACmd(ADC1, ENABLE);
}
/**
* @brief DMA1 channel0 and channel1 Interrupt routine.
* @param None
* @retval None
*/
INTERRUPT_HANDLER(DMA1_CHANNEL0_1_IRQHandler, 2)
{
/* In order to detect unexpected events during development,
it is recommended to set a breakpoint on the following instruction.
*/
/* Calculate Potentiometer RV voltage value*/
// Voltage = (uint32_t)((uint32_t)Buffer[0] * //(uint32_t)ADC_RATIO) / 1000;
/* Calculate BNC voltage value*/
//(uint32_t)((uint32_t)Buffer[1] * 1225) / 1000;
Verfin = (uint32_t)1224*4096/Buffer[1];
//GPIO_ToggleBits(GPIOB, GPIO_Pin_4);
/* Clear IT Pending Bit */
DMA_ClearITPendingBit(DMA1_IT_TC0);
}
上面時,c中的代碼,。h中的如下:
ifndef __ADC_H
#define __ADC_H
#include "stm8l15x.h"
//#include "stm8l15x_it.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define ADC1_DR_ADDRESS ((uint16_t)0x5344)
#define BUFFER_SIZE ((uint8_t) 0x02)
#define BUFFER_ADDRESS ((uint16_t)(&Buffer))
extern uint16_t Buffer[BUFFER_SIZE];
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
void ADC_Config(void);
void DMA_Config(void);
#endif
下面是main中的代碼:
#include "bsp.h"
int main( void )
{
SysInit();//bsp文件中包含了系統,adc與dma的初始化
/* Enable Interrupts */
enableInterrupts();
ADC_SoftwareStartConv(ADC1);//START,necessary 啓動adc轉換
while(1)
{
}
return 0;
}
從調試窗口中看到,Verfin = 2498,實際萬用表測
的電壓=2.49V,可見測量的數據還是挺準確的,另
外在3點多V電源情況測的值也基本準確。
最後,由於stm8L051的內存空間比較小,
還是希望能寄存器開發,這等待有空再參
考庫函數研究測量內部參考電壓的寄存器操作吧。