相關電路與IO引腳
注意:串口打印重定向后使用printf打印需要在keil里勾選?Use MicroLIB ,否則會卡住。?
參看:https://zhuanlan.zhihu.com/p/565613666
串口重定向:
/* USER CODE BEGIN Includes */#include <stdio.h>// 包含標準輸入輸出頭文件/* USER CODE END Includes */int fputc(int ch,FILE *f){//采用輪詢方式發送1字節數據,超時時間設置為無限等待HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,HAL_MAX_DELAY);return ch;}int fgetc(FILE *f){uint8_t ch=0;// 采用輪詢方式接收 1字節數據,超時時間設置為無限等待HAL_UART_Receive( &huart1,(uint8_t*)&ch,1, HAL_MAX_DELAY );return ch;}
ADC的GPIO復用引腳表:
?參考:
視頻教程:14.1和14.2節
【【14.1】STM32 ADC模數轉換器 感知世界的鑰匙——Kevin帶你讀《STM32Cube高效開發教程基礎篇》】 https://www.bilibili.com/video/BV1CV4y1k71M/?share_source=copy_web&vd_source=9332b8fc5ea8d349a54c3989f6189fd3
博客:
https://blog.csdn.net/little_grapes/article/details/121154513
ADC相關函數:
?實驗內容
1、利用 ADC1 通道 3 采樣 PA3 的電壓值,將 ADC 采樣值和轉換的電壓值通過串行口返回, 調節電位器,觀察運行結果。
根據前面的復用引腳表,選擇ADC1的通道IN3。
CubeMX配置如下,
采樣時間(sampling time)選擇55.5cycles,采樣時間長一些結果更準確。
因為也要使用中斷方式,所以要開啟中斷
?
輪詢方式:
/* USER CODE BEGIN 2 */HAL_ADCEx_Calibration_Start(&hadc1);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 *///輪詢HAL_ADC_Start(&hadc1);HAL_ADC_PollForConversion(&hadc1,50);//is it finished?if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1),HAL_ADC_STATE_REG_EOC)){adc_res=HAL_ADC_GetValue(&hadc1);printf("voltage value:%.1f V\r\n",adc_res*3.3/4095);}//延時一段時間再啟動轉換HAL_Delay(1000);}/* USER CODE END 3 */
?中斷方式(直接把輪詢相關的代碼替換,詳見參考的文章)
/* USER CODE BEGIN 2 *///中斷方式啟動ADC轉換HAL_ADC_Start_IT(&hadc1);/* USER CODE END 2 */
?回調函數:
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{if(hadc->Instance==ADC1){adc_res=HAL_ADC_GetValue(&hadc1);printf("voltage value:%.2f V,original value:%d \r\n",adc_res*3.3/4095,adc_res);}
}
2、編寫程序,利用光敏電阻設計光電開關,控制 LED1 點亮和熄滅。
光敏電阻對應引腳PA2,選擇ADC1的IN2通道,選擇使用定時器作為中斷源,注意此時要關閉連續轉換,cubemx配置:
記得開啟ADC中斷。
然后配置定時器,這里用定時器3,頻率為72mhz/(7200*5000)
?
?代碼:
/* USER CODE BEGIN 2 *///中斷方式啟動ADC轉換HAL_ADC_Start_IT(&hadc1);//開啟定時器3HAL_TIM_Base_Start(&htim3);/* USER CODE END 2 */
?回調函數(這里設置設置計算電壓的方法也是按照3.3V作為參考電壓,大于2.1V就點亮燈(這里點亮了兩個燈),燈的引腳看前面的GPIO實驗)
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{if(hadc->Instance==ADC1){adc_res=HAL_ADC_GetValue(&hadc1);// printf("voltage value:%.1f V\r\n",adc_res*3.3/4095);if(adc_res*3.3/4095>2.1){HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,0);HAL_GPIO_WritePin(GPIOF,GPIO_PIN_0,1);} else{HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,1);HAL_GPIO_WritePin(GPIOF,GPIO_PIN_0,0);}}
}
3、設計一個室內溫控系統,PA3 采樣電壓表示采集的溫度,閾值上限為 2.5V,下限為 1V,采樣電壓顯示在數碼管上。
(1)當采樣電壓低于 1V(溫度過低),蜂鳴器鳴叫(模擬聲音報警),LED1 閃爍(模 擬光報警),全彩燈打開(模擬加熱)。
(2)當采樣電壓位于 1V~2.5V 時,正常,蜂鳴器不叫,發光二極管不亮,電機不轉。
(3)當采樣電壓高于 2.5V 時(溫度過高),蜂鳴器鳴叫(模擬聲音報警),LED1 閃爍 (模擬光報警),電機旋轉(模擬風扇降溫)。
這里蜂鳴器(PB8)用定時器4通道3輸出一定頻率的PWM控制,led閃爍間隔時間用cnt控制,循環了一定次數才翻轉電平。配置如下:
段碼表10以后是原來的數字加上了小數點顯示?
/* USER CODE BEGIN 0 */uint8_t flag=0;int res=0;
//uint8_t table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x80 };//10表示'-'
uint8_t table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x80+0x3f,0x80+0x06,0x80+0x5b,0x80+0x4f,0x80+0x66,0x80+0x6d,0x80+0x7d,0x80+0x07,
0x80+0x7f,0x80+0x6f, };//10表示'-'
uint8_t s[]={0,0,0,0,0,0,10,0};
uint16_t adc_res=0;
int light_flag=0;uint8_t n1;uint8_t n2;void write_byte(uint8_t date){unsigned char i;for(i=0;i<8;i++){HAL_GPIO_WritePin(GPIOA,GPIO_PIN_7,(date>>(7-i))&0x01);HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,1);HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,0);}HAL_GPIO_WritePin(GPIOA,GPIO_PIN_8,1);HAL_GPIO_WritePin(GPIOA,GPIO_PIN_8,0);}int fputc(int ch,FILE *f){//采用輪詢方式發?1字節數據,超時時間設置為無限等待HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,HAL_MAX_DELAY);return ch;}int fgetc(FILE *f){uint8_t ch=0;// 采用輪詢方式接收 1字節數據,超時時間設置為無限等待HAL_UART_Receive( &huart1,(uint8_t*)&ch,1, HAL_MAX_DELAY );return ch;}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{if(hadc->Instance==ADC1){adc_res=HAL_ADC_GetValue(&hadc1);float vol=adc_res*3.3/4095;printf("voltage value:%.2f V\r\n",vol);if(vol <1){HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,0);light_flag=1;HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, 0);HAL_GPIO_WritePin(GPIOD, GPIO_PIN_13, 0);HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_3);} else if(adc_res*3.3/4095 >=1 &&adc_res*3.3/4095<=2.5){HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,1);HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, 0);HAL_GPIO_WritePin(GPIOD, GPIO_PIN_13, 0);HAL_TIM_PWM_Stop(&htim4,TIM_CHANNEL_3);light_flag=0;}else{light_flag=1;HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, 1);HAL_GPIO_WritePin(GPIOD, GPIO_PIN_13, 0);HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_3); }n1=(uint8_t)vol;n2=(uint8_t)(vol*10)%10;//printf(" value:%d V\r\n",n1);//printf(" value:%d V\r\n",n2);}
}
int cnt=0;/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */if(light_flag==1){cnt++;if(cnt==50){cnt=0;HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_0);}}else{HAL_GPIO_WritePin(GPIOF,GPIO_PIN_0,0);cnt=0;}s[7]=n2;s[6]=n1+10;for(int i=8;i<11;i++){write_byte(table[s[15-i]]);HAL_GPIO_WritePin(GPIOF,0x01<<i,0);HAL_Delay(1);HAL_GPIO_WritePin(GPIOF,0x01<<i,1);}}/* USER CODE END 3 */
源文件見個人主頁。