- 使用標準庫實現本次功能的源代碼已上傳:
- https://github.com/yzmj0986/STM32_Std.lib_ADC_Voltage.git
MCU:STM32F103ZET6
IDE: MDK-ARM V5 +STM32CubeMX5.0.0
串口調試助手:SSCOM3.2
功能描述:通過ADC1通道1採樣外部電壓值,將採樣的AD值和轉換後的電壓值通過串口打印出來。需要配置的有USART1和ADC。
一. 在 Pinout&Configuration---System Core中:
- 1. 首先設置時鐘RCC的HSE(外部高速時鐘)爲晶振模式:Crystal/ceramic Resonator
- 2. 設置系統SYS的Debug爲Serial Wire:
二. 在 Pinout&Configuration---Analog和Connectivity中:
- 1. 設置PA1爲ADC1_IN1模式:
根據原理圖可知ADC1的通道1的引腳爲PA1,因此設置PA1爲ADC1_IN1模式。
- 2. 在Configuration的Parameter Settings中設置ADC1的參數:
分別設置模式,單單個掃描和單次掃描,並在規則通道參數設置中設置爲軟件觸發的方式。(對應的標準庫代碼在右上角)。
- 3. 打開USART1,並設置模式爲異步收發模式Asynchronous:
- 4. 設置USART1的參數,通用的“96-N-8-1”模式,即波特率9600,N校驗位(無校驗),數據位數爲8,停止位爲1位:
三.在 Clock Configuration中:
配置時鐘爲72 Mhz。
四.在 Project Manager---Project中:
- 1.設置項目的名稱以及保存的位置,選擇Toolchain/IDE爲MDK-ARM V5,
Tips:最好把Linker Settings中的Minimum Heap Size設置爲0x600。
- 2.在Code Generator選項中如下勾選:
最後點Generate Code生成代碼,並選擇“Open Project”:
五.代碼分析與改寫:
和筆記4相同,同樣需要用到串口輸出的功能,首先將printf()函數的輸出功能映射到串口上:
- 1. 首先在main.c中進行宏定義:
/* Private function prototypes -----------------------------------------------*/
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
- 2. 對於MDK-ARM編譯器,在main.c中加入重定向函數:(此處與官方例程中不同,將&UartHandle改爲&huart1)
/* USER CODE BEGIN 0 */
int fputc(int ch,FILE *f)
{
HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xFFFF);
return ch;
}
/* USER CODE END 0 */
3. 在main.c中設置變量用於存儲AD和電壓值:(注意VOL_Value一定是浮點型的)
/* USER CODE BEGIN 1 */
uint16_t ADC_Value;
float VOL_Value;
/* USER CODE END 1 */
4.在while(1)循環中添加AD與電壓轉換程序:
步驟依次爲:
① HAL_ADCEx_Calibration_Start()//校準ADC
② HAL_ADC_Start()//開啓ADC
③ HAL_ADC_PollForConversion()//等待轉換過程
④若if循環判斷轉換完成後,HAL_ADC_GetState()獲取AD值存在ADC_Value中並打印。
⑤將AD值轉換爲電壓值存在VOL_Value中並打印。
/* USER CODE BEGIN WHILE */
while (1)
{
HAL_ADCEx_Calibration_Start(&hadc1); //校準
HAL_ADC_Start(&hadc1); //開啓
HAL_ADC_PollForConversion(&hadc1,50); //等待轉換完成
if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))
{
ADC_Value=HAL_ADC_GetState(&hadc1);
printf("檢測AD值爲:%d\r\n",ADC_Value);
VOL_Value=ADC_Value*3.3/4096;
printf("檢測電壓值爲:%.2fV \r\n",VOL_Value);
}
HAL_Delay(200);
/* USER CODE END WHILE */
至此應該是完成了HAL庫下ADC轉換讀取電壓的程序,但是不知是硬件出了問題還是軟件有邏輯錯誤,我的電壓值一直很小,變化也不大,希望有遇到相同問題的朋友可以交流一下。(基於標準庫函數的程序也遇到了這個問題)。
2019/2/20 10:23 更新:
針對上述問題,經過反覆檢查程序找到了問題。源程序如下:
u16 Get_ADC_Value(u8 ch,u8 times) //獲取AD轉換值的結果
{
u8 t;
u8 temp_val=0;
ADC_RegularChannelConfig(ADC1,ch,1,ADC_SampleTime_239Cycles5); //最大的轉換週期,239.5個
for (t=0;t<times;t++)
{
ADC_SoftwareStartConvCmd(ADC1,ENABLE);
while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)); //轉換完成後退出
temp_val+=ADC_GetConversionValue(ADC1);
delay_ms(5);
}
return temp_val/times;
temp_val的取值範圍是0-4095,因此應定義爲32位的變量:u8 temp_val=0→u32 temp_val=0;
針對HAL庫中程序,一定要定義VOL_Value爲浮點型的。
則會得到正確的結果: