ADC工作均為非阻塞狀態 輪詢模式 中斷模式 DMA模式 庫函數: 校準模式: 校準ADC(HAL_ADCEx_Calibration_Start(&hadc);有些晶元不支持校準,F4不支持 可變占空比設置 1 /* 2 3 實際使用時空置引腳狀態下會飄動,大致為3.3V的一半,是晶元內部的原因 ...
ADC工作均為非阻塞狀態
輪詢模式
中斷模式
DMA模式
庫函數:
1 HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef* hadc);//輪詢模式,需放在迴圈中不斷開啟 2 3 HAL_StatusTypeDef HAL_ADC_Stop(ADC_HandleTypeDef* hadc); 4 5 HAL_StatusTypeDef HAL_ADC_PollForConversion(ADC_HandleTypeDef* hadc, uint32_t Timeout);//等待轉換結束,只適用於輪詢 6 7 HAL_StatusTypeDef HAL_ADC_PollForEvent(ADC_HandleTypeDef* hadc, uint32_t EventType, uint32_t Timeout);// 8 9 HAL_StatusTypeDef HAL_ADC_Start_IT(ADC_HandleTypeDef* hadc);//中斷模式 10 11 HAL_StatusTypeDef HAL_ADC_Stop_IT(ADC_HandleTypeDef* hadc); 12 13 void HAL_ADC_IRQHandler(ADC_HandleTypeDef* hadc);//中斷 14 15 HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length);//DMA模式 16 17 HAL_StatusTypeDef HAL_ADC_Stop_DMA(ADC_HandleTypeDef* hadc); 18 19 uint32_t HAL_ADC_GetValue(ADC_HandleTypeDef* hadc); //讀取ADC的值 20 21 void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc);//結束後回調 22 23 void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc);//轉換過程中回調 24 25 void HAL_ADC_LevelOutOfWindowCallback(ADC_HandleTypeDef* hadc); 26 27 void HAL_ADC_ErrorCallback(ADC_HandleTypeDef *hadc);
校準模式:
校準ADC(HAL_ADCEx_Calibration_Start(&hadc);有些晶元不支持校準,F4不支持
----------------------------------------------------------------------------------------------------------------------------------
可變占空比設置
1 /* 2 3 實際使用時空置引腳狀態下會飄動,大致為3.3V的一半,是晶元內部的原因 4 5 解決方式:引腳設置為下拉輸入,F4沒有這個設置 6 7 */ 8 9 /* USER CODE BEGIN 2 */ 10 11 // HAL_ADC_Start_IT(&hadc1);//開啟ad轉換 12 13 HAL_TIM_Base_Start_IT(&htim3);//定時器中斷 14 15 HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_2);//開啟輸出pwm 16 17 /* USER CODE END 2 */ 18 19 /* Infinite loop */ 20 21 /* USER CODE BEGIN WHILE */ 22 23 while (1) 24 25 { 26 27 /* USER CODE END WHILE */ 28 29 /* USER CODE BEGIN 3 */ 30 31 float pwmOut ; 32 33 float dutyRatio; 34 35 int lastTickMs=0; 36 37 HAL_ADC_Start(&hadc1); 38 39 40 41 if(HAL_GetTick() - lastTickMs >= 1000) 42 43 { 44 45 HAL_GPIO_TogglePin(RUNNING_LED_GPIO_Port,RUNNING_LED_Pin); 46 47 lastTickMs = HAL_GetTick(); 48 49 } 50 51 HAL_Delay(1000); 52 53 adcConvertedValue=HAL_ADC_GetValue(&hadc1);//獲取AD轉換值 54 55 adcConvertedVoltage =(double)adcConvertedValue*3.3/4096; 56 57 58 59 pwmOut = adcConvertedValue*2400/4096; 60 61 dutyRatio = pwmOut/2400 ; 62 63 TIM3->CCR2 = pwmOut; //(pwmOut)/ 2400 change Duty ratio 64 65 66 67 printf("AD轉換原始值 = %d\r\n", adcConvertedValue); 68 69 printf("計算得出電壓值 = %f V \r\n",adcConvertedVoltage); 70 71 printf("實際輸出pwm值 = %f\r\n", pwmOut); 72 73 printf("占空比 = %f%%\r\n",dutyRatio*100); 74 75 } 76 77 /* USER CODE END 3 */ 78 79 }
手動更改占空比
TIM3->CCR2 改變占空比
TIM3->ARR 改變頻率
TIM3->PSC
ADC_EXIT 觸發引腳
32晶元自帶的溫度感測器,在16或者18通道
可以用來做對比
代碼:
1 //對於12位的ADC,3.3V的ADC值為0xfff,溫度為25度時對應的電壓值為1.43V即0x6EE 2 #define V25 0x6EE 3 //斜率 每攝氏度4.3mV 對應每攝氏度0x05 4 #define AVG_SLOPE 0x05 5 6 7 /* 啟動AD轉換並使能DMA傳輸和中斷 */ 8 HAL_ADC_Start_DMA(&hadcx,(uint32_t *)&ADC_ConvertedValue,sizeof(ADC_ConvertedValue)); 9 10 /* 無限迴圈 */ 11 while (1) 12 { 13 HAL_Delay(1000); 14 Current_Temperature = (V25-ADC_ConvertedValue)/AVG_SLOPE+25; //計算公式 15 /* 10進位顯示 */ 16 printf("The IC current temperature = %d->%3d ℃\n",ADC_ConvertedValue,Current_Temperature); 17 // /* 16進位顯示 */ 18 // printf("The current temperature= %04x \n", Current_Temperature); 19 }
應用:測量壓敏電阻阻值---還是測電壓
1 while (1) 2 { 3 HAL_Delay(1000); 4 /* 3.3為AD轉換的參考電壓值,stm32的AD轉換為12bit,2^12=4096, 5 即當輸入為3.3V時,AD轉換結果為4096 */ 6 ADC_ConvertedValueLocal =(float)ADC_ConvertedValue*3.3/4096; 7 flexiforce_R = 3.3*20/ADC_ConvertedValueLocal; // V(out) = Rref * Vcc / R; Rref=20K Vcc=3.3V 8 printf("AD轉換原始值 = 0x%04X \r\n", ADC_ConvertedValue); 9 printf("計算得出電壓值 = %f V \r\n",ADC_ConvertedValueLocal); 10 printf("計算得出電阻值 = %f KR\n",flexiforce_R); 11 }
DMA多通道採集-----開啟多通道設置,定義一個數組存放轉換值
1 while (1) 2 { 3 HAL_Delay(1000); 4 /* 3.3為AD轉換的參考電壓值,stm32的AD轉換為12bit,2^12=4096, 5 即當輸入為3.3V時,AD轉換結果為4096 */ 6 ADC_ConvertedValueLocal[0] =(float)(ADC_ConvertedValue[0]&0xFFF)*3.3/4096; // ADC_ConvertedValue[0]只取最低12有效數據 7 ADC_ConvertedValueLocal[1] =(float)(ADC_ConvertedValue[1]&0xFFF)*3.3/4096; // ADC_ConvertedValue[1]只取最低12有效數據 8 ADC_ConvertedValueLocal[2] =(float)(ADC_ConvertedValue[2]&0xFFF)*3.3/4096; // ADC_ConvertedValue[2]只取最低12有效數據 9 ADC_ConvertedValueLocal[3] =(float)(ADC_ConvertedValue[3]&0xFFF)*3.3/4096; // ADC_ConvertedValue[3]只取最低12有效數據 10 11 printf("CH1_PC0 value = %d -> %fV\n",ADC_ConvertedValue[0]&0xFFF,ADC_ConvertedValueLocal[0]); 12 printf("CH2_PC1 value = %d -> %fV\n",ADC_ConvertedValue[1]&0xFFF,ADC_ConvertedValueLocal[1]); 13 printf("CH3_PC2 value = %d -> %fV\n",ADC_ConvertedValue[2]&0xFFF,ADC_ConvertedValueLocal[2]); 14 printf("CH4_PC3 value = %d -> %fV\n",ADC_ConvertedValue[3]&0xFFF,ADC_ConvertedValueLocal[3]); 15 16 printf("已經完成AD轉換次數:%d\n",DMA_Transfer_Complete_Count); 17 DMA_Transfer_Complete_Count=0; 18 printf("\n"); 19 }
交叉模式---目的是兩路ADC採集一路信號,可以獲取雙倍速度
1 /* 啟動AD轉換並使能DMA傳輸和中斷 */ 2 HAL_ADC_Start(&hadcx2); 3 HAL_ADCEx_MultiModeStart_DMA(&hadcx1,&ADC_ConvertedValue,sizeof(ADC_ConvertedValue)); //開啟 4 5 /* 無限迴圈 */ 6 while (1) 7 { 8 HAL_Delay(1000); 9 /* 3.3為AD轉換的參考電壓值,stm32的AD轉換為12bit,2^12=4096, 10 即當輸入為3.3V時,AD轉換結果為4096 */ 11 ADC_ConvertedValueLocal[0] =(float)(ADC_ConvertedValue&0xFFF)*3.3/4096; //ADC1 12 ADC_ConvertedValueLocal[1] =(float)((ADC_ConvertedValue>>16)&0xFFF)*3.3/4096; //ADC2 13 14 printf("ADC1轉換原始值 = 0x%04X --> 電壓值 = %f V \n", ADC_ConvertedValue&0xFFFF,ADC_ConvertedValueLocal[0]); 15 printf("ADC2轉換原始值 = 0x%04X --> 電壓值 = %f V \n", (ADC_ConvertedValue>>16)&0xFFFF,ADC_ConvertedValueLocal[1]); 16 printf("已經完成AD轉換次數:%d\n",DMA_Transfer_Complete_Count); 17 printf("\r\n"); 18 DMA_Transfer_Complete_Count=0; 19 }
DAC---數據轉換
基本配置:
初始化
設置通道
啟動DAC
在迴圈中改變dac_value值即可
庫函數:
1 /* IO operation functions *****************************************************/ 2 HAL_StatusTypeDef HAL_DAC_Start(DAC_HandleTypeDef* hdac, uint32_t Channel); 3 HAL_StatusTypeDef HAL_DAC_Stop(DAC_HandleTypeDef* hdac, uint32_t Channel); 4 HAL_StatusTypeDef HAL_DAC_Start_DMA(DAC_HandleTypeDef* hdac, uint32_t Channel, uint32_t* pData, uint32_t Length, uint32_t Alignment); //需要函數中不斷開啟 5 HAL_StatusTypeDef HAL_DAC_Stop_DMA(DAC_HandleTypeDef* hdac, uint32_t Channel); 6 HAL_StatusTypeDef HAL_DAC_SetValue(DAC_HandleTypeDef* hdac, uint32_t Channel, uint32_t Alignment, uint32_t Data); 7 uint32_t HAL_DAC_GetValue(DAC_HandleTypeDef* hdac, uint32_t Channel); 8 9 /* 初始化DAC */ 10 MX_DAC_Init(); 11 /* 設置DAC通道值 */ 12 HAL_DAC_SetValue(&hdac, DACx_CHANNEL, DAC_ALIGN_8B_R, dac_value); 13 /* 啟動DAC */ 14 HAL_DAC_Start(&hdac, DACx_CHANNEL); 15 16 /* 無限迴圈 */ 17 while (1) 18 { 19 /* KEY1增加輸出電壓 */ 20 if(KEY1_StateRead()==KEY_DOWN) 21 { 22 if(dac_value<245) 23 dac_value+=10; 24 else 25 dac_value=255; 26 HAL_DAC_SetValue(&hdac, DACx_CHANNEL, DAC_ALIGN_8B_R, dac_value); //設置值 27 } 28 /* KEY2減少輸出電壓 */ 29 if(KEY2_StateRead()==KEY_DOWN) 30 { 31 if(dac_value>10) 32 dac_value-=10; 33 else 34 dac_value=0; 35 HAL_DAC_SetValue(&hdac, DACx_CHANNEL, DAC_ALIGN_8B_R, dac_value); 36 } 37 }
輸出正弦波----DMA模式
就是預設一組值,不斷改變
1 const uint16_t CH_value[32] = { 2 2448,2832,3186,3496,3751,3940,4057,4095,4057,3940, 3 3751,3496,3186,2832,2448,2048,1648,1264,910,600,345, 4 156,39,0,39,156,345,600,910,1264,1648,2048 5 }; 6 7 8 9 10 int main(void) 11 { 12 /* 複位所有外設,初始化Flash介面和系統滴答定時器 */ 13 HAL_Init(); 14 /* 配置系統時鐘 */ 15 SystemClock_Config(); 16 17 18 /* 初始化DAC */ 19 MX_DAC_Init(); 20 /* 啟動定時器 */ 21 HAL_TIM_Base_Start(&htim6); 22 /* 啟動DAC DMA功能 */ 23 HAL_DAC_Start_DMA(&hdac,DACx_CHANNEL,(uint32_t *)CH_value,32,DAC_ALIGN_12B_R); 24 /* 無限迴圈 */ 25 while (1) 26 { 27 28 } 29 }
2019-03-26