STM32CubeMx學習之——基於藍橋杯物聯網開發板實現AD轉換和OLED顯示外加串口的綜合小例程
本實驗主要是利用OLED顯示AD轉換的結果和利用OLED字庫顯示漢字,外加串口通信做輔助調試。
OLED上電不顯示任何信息,通過串口向上位機發送字符“S”時,則OLED第一行顯示“AD量化值:XXXX”,第二行顯示“AD電壓值:X.XX”。向上位機發送字符“E”時,OLED第一行顯示“AD採集結束”。
其次上位機通過串口助手可以看到AD轉換的值,其顯示格式與上此實驗一致。
目錄
1、利用STM32CubeMx配置外設及創建工程代碼
2、程序配置(重要!)
將官網的這三個.c文件複製到創建好工程文件的Src文件夾下
將官網的這兩個.h文件複製到創建好工程文件的Inc文件夾下,然後打開工程。
將剛纔複製過去的三個.c文件添加到工程中
3、部分代碼參考
/* USER CODE BEGIN PV */
uint8_t Rx_buf = 0; //串口接收數據變量,用來存儲串口發送的數據位
uint8_t Rx_Flag = 0; //串口接收數據標誌位,用做開啓AD採集的開始和停止
uint8_t string[50]; //sprintf函數數據緩衝數組
float ADC_Volt = 0; //用來接收AD量化值的變量
uint16_t ADC_Value = 0; //用來存儲AD量化值轉換爲電壓值的變量
/* USER CODE END PV */
/* USER CODE BEGIN 0 */
/**
* @brief 串口2發送AD採集數據信息。
* @param None
* @retval None
*/
void USART2_Send_ADStart(void)
{
sprintf((char *)string, "ADC_Value:%4d, ADC_Volt:%.2f\r\n", ADC_Value, ADC_Volt); //
HAL_UART_Transmit(&huart2, string, sizeof(string), 10000);
}
/**
* @brief 串口2發送AD採集結束信息。
* @param None
* @retval None
*/
void USART2_Send_ADStop(void)
{
sprintf((char *)string, "AD採集結束\r\n");
HAL_UART_Transmit(&huart2, string, sizeof(string), 10000);
}
/**
* @brief OLED上電顯示初始化函數。
* @param None
* @retval None
*/
void OLED_Display_Init(void)
{
OLED_PowerControl(ENABLE); //控制OLED引腳(PB5)使能,也即是給OLED上電
HAL_Delay(200); //延時200ms
OLED_Init(); //OLED初始化
OLED_Clear(); //OLED清屏
}
/**
* @brief OLED顯示字符函數,主要用來顯示第一行和第二行的文字信息。這裏要注意一個漢字所佔的是4個字節,高度和寬度各佔2個字節
* @param None
* @retval None
*/
void OLED_Display_ADStart_Chinese(void)
{
sprintf((char *)string, "AD");
OLED_ShowString(2, 0, string, 16); //這裏顯示字符的大小尺寸是16,也就是一個字符佔2個字節,寬度佔一個字節,高度佔兩個字節
sprintf((char *)string, "AD");
OLED_ShowString(2, 2, string, 16);
OLED_ShowCHinese(18, 0, 0); //顯示漢字“量”
OLED_ShowCHinese(34, 0, 1); //顯示漢字“化”
OLED_ShowCHinese(50, 0, 2); //顯示漢字“值”
OLED_ShowCHinese(18, 2, 3); //顯示漢字“電”
OLED_ShowCHinese(34, 2, 4); //顯示漢字“壓”
OLED_ShowCHinese(50, 2, 5); //顯示漢字“值”
sprintf((char *)string, ":%4d", ADC_Value); //這裏的ADC_Value的佔位符要寫成4位整形格式,不然顯示到OLED屏幕上的數值在小於1000的時候會刷新不正確!!!
OLED_ShowString(68, 0, string, 16);
sprintf((char *)string, ":%.2fV", ADC_Volt);
OLED_ShowString(68, 2, string, 16);
}
/**
* @brief OLED顯示AD採集結束信息。
* @param None
* @retval None
*/
void OLED_Display_ADStop_Chinese(void)
{
sprintf((char *)string, "AD");
OLED_ShowString(2, 0, string, 16);
OLED_ShowCHinese(18, 0, 6); //顯示漢字“採”
OLED_ShowCHinese(34, 0, 7); //顯示漢字“集”
OLED_ShowCHinese(50, 0, 8); //顯示漢字“結”
OLED_ShowCHinese(66, 0, 9); //顯示漢字“束”
sprintf((char *)string, " "); //清除第一行的顯示AD量化值
OLED_ShowString(82, 0, string, 16);
sprintf((char *)string, " "); //清屏第二行
OLED_ShowString(0, 2, string, 16);
}
/* USER CODE END 0 */
/* USER CODE BEGIN 2 */
HAL_UART_Receive_IT(&huart2, &Rx_buf, 1); //開啓串口2中斷
OLED_Display_Init(); //OLED上電初始化函數
/* USER CODE END 2 */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
//如果開發板串口2接收開始AD轉換的字符,則開啓AD轉換,向上位機發送AD轉換的數據,並且OLED顯示AD轉換的數據
if(Rx_Flag == 1)
{
HAL_ADC_Start_IT(&hadc); //打開AD轉換
USART2_Send_ADStart(); //串口2向上位機發送AD轉化的數據
OLED_Display_ADStart_Chinese(); //OLED顯示AD轉換的文字信息
HAL_Delay(1000); //延遲1S,這裏延時的目的是爲了,串口向上位機發送數據的時候慢一點,也可不加
}
//如果開發板串口2接收開始AD轉換結束的字符,則關閉AD轉換,向上位機發送AD轉換關閉的文字,並且OLED顯示AD採集結束
else if(Rx_Flag == 2)
{
HAL_ADC_Stop_IT(&hadc); //關閉AD轉換
USART2_Send_ADStop(); //串口2向上位機發送AD採集結束的文字信息
OLED_Display_ADStop_Chinese(); //OLED顯示AD採集結束的文字信息
HAL_Delay(1000); //延遲1S,這裏延時的目的是爲了,串口向上位機發送數據的時候慢一點,也可不加
}
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
/* USER CODE BEGIN 4 */
/**
* @brief ADC開始採集數據的回調函數。
* @param hadc:ADC通道
* @retval None
*/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
ADC_Value = HAL_ADC_GetValue(hadc); //返回ADC轉換的電壓量化值
ADC_Volt = ADC_Value * 3.3 / 4096; //將量化值轉換爲電壓值
}
/* USER CODE BEGIN 4 */
/**
* @brief 串口2接收數據的回調函數。
* @param huart:串口通道
* @retval None
*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART2)
{
if(Rx_buf == 'S')
{
Rx_Flag = 1; //如果接收到的字符爲‘S’,則標誌位爲1,在主函數中進行判斷,以此打開AD轉換
}
else if(Rx_buf == 'E')
{
Rx_Flag = 2; //如果接收到的字符爲‘E’,則標誌位爲2,在主函數中進行判斷,以此關閉AD轉換
}
HAL_UART_Receive_IT(&huart2, &Rx_buf, 1); //重新開啓串口2中斷
}
}
/* USER CODE END 4 */
/**
* @brief OLED屏幕顯示一組漢字。
* @param x 橫向選擇位置;
y 縱向選擇位置;
no 需要顯示的漢字標號;
* @retval None
*/
void OLED_ShowCHinese(uint8_t x,uint8_t y,uint8_t no)
{
uint8_t t,adder=0;
OLED_SetPos(x,y);
for(t=0;t<16;t++)
{
OLED_Write(TYPE_DATA, Hzk[2*no][t]);
adder+=1;
}
OLED_SetPos(x,y+1);
for(t=0;t<16;t++)
{
OLED_Write(TYPE_DATA, Hzk[2*no+1][t]);
adder+=1;
}
}
最後一定要注意,想要OLED顯示漢字,就一定要加上上面這個顯示漢字的函數!!!
4、實驗現象
5、結束語
這次的實驗主要是想讓OLED顯示漢字來着,其他內容全部都是之前實驗的內容。串口也不必要開,只是我用作調程序,就沒有再刪掉了。官網提供的程序中沒有顯示漢字的函數,這裏我從其他地方找的漢字顯示函數,然後稍稍修改了下。想要顯示漢字一定要注意加上這個函數,如果不想麻煩找,評論留下郵箱,我把上面用到的三個.c文件和兩個.h文件私發郵箱。還有就是在使用取字模軟件的時候,要進行一下取字模設置,這裏我用的取字模軟件是PCtoLCD2002,要把“取模方式”改成“列行式”,“取模走向”選擇“逆向”,“點陣格式”選擇“陰碼”。可能不同的取模軟件配置不太一樣,應該也都大同小異,注意一下就好。
還要注意在OLED_Display_ADStart_Chinese這個函數的ADC_Value的佔位符要寫成4位整形格式,不然顯示到OLED屏幕上的數值在小於1000的時候會刷新不正確!!!