一、項目介紹
當前介紹的項目是基于 STM32F103ZET6 系列 MCU 設(shè)計的數(shù)顯熱水器,通過顯示屏來顯示熱水器的溫度及其工作狀態(tài),通過 PT100 傳感器來檢測熱水器的溫度變化,并通過電加熱片實現(xiàn)加熱過程,以達到控制熱水器溫度的目的。
二、設(shè)計流程
2.1 硬件選型
2.2 軟件設(shè)計
(1)顯示屏
使用 OLED 顯示屏來顯示熱水器的溫度及其工作狀態(tài),通過 SPI 接口與 STM32 芯片進行通訊。設(shè)計溫度值及其單位、熱水器工作狀態(tài)等。
(2)溫度傳感器
使用 PT100 溫度傳感器來檢測熱水器內(nèi)部溫度的變化,并將數(shù)據(jù)通過 ADC 轉(zhuǎn)換后,傳輸給 STM32 芯片,以實現(xiàn)對熱水器加熱過程的控制。
(3)電加熱片
使用電加熱片模擬熱水器加熱過程,通過繼電器控制電加熱片的通斷,以調(diào)節(jié)熱水器的溫度。
(4)控制系統(tǒng)
通過 STM32 芯片來實現(xiàn)對熱水器的控制,讀取溫度傳感器的數(shù)據(jù)。
三、代碼設(shè)計
3.1 OLED顯示屏
(1)SPI 接口初始化
需要對 STM32F103ZET6 的 SPI 接口進行初始化配置,設(shè)置相關(guān)的時鐘和模式,使其能夠與 OLED 顯示屏進行通訊。
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE); // 打開SPI3時鐘
SPI_InitTypeDef spi_init_type;
spi_init_type.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
spi_init_type.SPI_Mode = SPI_Mode_Master;
spi_init_type.SPI_DataSize = SPI_DataSize_8b;
spi_init_type.SPI_CPOL = SPI_CPOL_Low;
spi_init_type.SPI_CPHA = SPI_CPHA_1Edge;
spi_init_type.SPI_NSS = SPI_NSS_Soft;
spi_init_type.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32; // 設(shè)置 SPI 時鐘頻率為 72 MHz / 32 = 2.25MHz
spi_init_type.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_Init(SPI3, &spi_init_type);
SPI_Cmd(SPI3, ENABLE);
(2)OLED 顯示屏初始化
以下是 OLED 顯示屏的初始化代碼:
void OLED_Init(void) {
GPIO_SetBits(GPIOB, GPIO_Pin_6); //RST SET
GPIO_ResetBits(GPIOB, GPIO_Pin_6); //RST RESET
GPIO_SetBits(GPIOB, GPIO_Pin_6); //RST SET
?
write_command(0xAE); // 關(guān)閉顯示
write_command(0xD5); // 設(shè)置時鐘分頻因子,震蕩頻率
write_command(0x80); // 分頻因子=1 ,震蕩頻率(fosc)=8MHz
write_command(0xA8); // 設(shè)置驅(qū)動路數(shù):MUX(復用方式)
write_command(0x1F); // 1/32 duty (0x0F~0x3F)
write_command(0xD3); // 設(shè)置顯示偏移
write_command(0x00); // 不偏移
write_command(0x40); // 設(shè)置顯示開始行[5:0], 對于設(shè)置了32行的液晶,
// 這里的值為0表示從0行開始顯示
write_command(0x8D); // 對比度設(shè)置
write_command(0x14); // AHB參考電壓256等分 移位[3:0]100[n,1/256]
write_command(0x20); // 水平方向上的尋址模式
write_command(0x00); // 垂直方向上的尋址模式
write_command(0xA1); // 設(shè)置段再映射
write_command(0xC0); // 設(shè)置COM掃描方向
write_command(0xDA); // 設(shè)置COM引腳硬件配置
write_command(0x12);
write_command(0x81); // 對比度設(shè)置
write_command(0xBF); // 設(shè)置電荷泵電壓
write_command(0xD9); // 設(shè)置預充電周期
write_command(0xF1);
write_command(0xDB); // 設(shè)置VCOMH電壓倍率
write_command(0x40);
write_command(0xAF); // 打開顯示
?
OLED_Clear(); // 清屏
}
(3)OLED 顯示函數(shù)
接下來編寫 OLED 顯示函數(shù),實現(xiàn)字符和數(shù)字的顯示功能。
void OLED_show_string(uint8_t x, uint8_t y, char *str) {
uint8_t i = 0;
while (str[i] != '') {
OLED_show_char(x, y + i * 8, str[i]);
++i;
}
}
?
void OLED_show_char(uint8_t x, uint8_t y, char ch) {
uint8_t c = ch - 32;
if (c >= 96) return;
uint8_t* buffer = (uint8_t*)oled_buffer;
uint8_t cx, cy;
for (cy = 0; cy < 8; cy++) {
uint8_t line = font[c][cy];
for (cx = 0; cx < 6; cx++) {
if (line & 0x1) {
buffer[(y + cy) * OLEDWIDTH + x + cx] = 1;
} else {
buffer[(y + cy) * OLEDWIDTH + x + cx] = 0;
}
line > >= 1;
}
}
OLED_Draw_Pixel(x + 6, y, 0);
OLED_Draw_Pixel(x + 6, y + 1, 0);
OLED_Draw_Pixel(x + 6, y + 6, 0);
OLED_Draw_Pixel(x + 6, y + 7, 0);
}
(4)結(jié)果顯示
在代碼中調(diào)用 OLED_show_string 函數(shù)和 OLED_show_char 函數(shù)顯示數(shù)值和字符。
OLED_Init();
OLED_Clear();
OLED_show_string(0, 0, "HELLO WORLD!");
OLED_show_string(0, 16, "TEMP:20 C");
3.2 測溫代碼
(1)引腳配置
需要對 STM32F103ZET6 的 IO 口進行配置,將用于連接 PT100 溫度傳感器的引腳設(shè)置為輸入模式。
這里以 PA0 引腳作為 PT100 傳感器的連接口(即 PT100 三線連接中的 R3 端),代碼如下:
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉輸入模式
GPIO_Init(GPIOA, &GPIO_InitStructure);
(2)ADC 配置
接下來需要對 STM32F103ZET6 的 ADC 進行初始化配置,使其能夠讀取 PT100 溫度傳感器輸出的電壓信號。
這里以 ADC1 通道5 作為讀取口,代碼如下:
ADC_InitTypeDef ADC_InitStructure;
RCC_ADCCLKConfig(RCC_PCLK2_Div6); // 設(shè)置 ADC 時鐘為 PCLK2 的 1/6
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); // 打開 ADC1 時鐘
ADC_DeInit(ADC1); // 初始化 ADC1
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; // 連續(xù)轉(zhuǎn)換模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_Cmd(ADC1, ENABLE); // 開啟 ADC1
(3)溫度轉(zhuǎn)換函數(shù)
根據(jù) PT100 溫度傳感器輸出電壓與溫度的關(guān)系,可使用線性函數(shù)計算出溫度值。
轉(zhuǎn)換公式如下:
Rt = (Vref - Vpt) / Ipt // Rt 為 PT100 的阻值,Vref 為基準電壓,Vpt 為 PT100 輸出電壓,Ipt 為 PT100 驅(qū)動電流
Temp = a * Rt + b // Temp 為溫度值,a 和 b 為經(jīng)過擬合后的系數(shù)
其中 Rt 的計算需要使用差分運算放大器進行轉(zhuǎn)換,這里不再贅述。假設(shè)已經(jīng)得到 Rt 值,則溫度轉(zhuǎn)換函數(shù)代碼如下:
float PT100_Get_Temperature(float Rt)
{
float a = 3.9083e-3f, b = -5.775e-7f, R0 = 100.0f; // 根據(jù)實際數(shù)據(jù)進行擬合得到 a、b 和 R0 的值
float Tem, delta;
delta = pow(Rt / R0, 2) + a * (Rt / R0) + b;
Tem = (delta > 0) ? (-R0*a + sqrt(delta)) / (2 * b) : 0;
return Tem;
}
(4)數(shù)據(jù)采集
根據(jù)差分放大器輸出的電壓值得到 PT100 溫度傳感器的阻值,再根據(jù)阻值計算出實際溫度,最后將溫度值通過串口打印出來。以下是數(shù)據(jù)采集代碼:
float ADC_Get_Voltage(void)
{
float voltage = 0;
uint16_t adc_val = 0;
ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 1, ADC_SampleTime_239Cycles5); // 配置 ADC 通道5
ADC_SoftwareStartConvCmd(ADC1, ENABLE); // 使能軟件觸發(fā) ADC 轉(zhuǎn)換
while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)); // 等待轉(zhuǎn)換結(jié)束
adc_val = ADC_GetConversionValue(ADC1); // 讀取 ADC 轉(zhuǎn)換結(jié)果
voltage = (float)adc_val * 3.3f / 4096; // 計算基準電壓
return voltage;
}
float PT100_Get_Rt(float Vpt)
{
float Rsource = 10e3f, Rpt = 100.0f; // Rsource 為差分放大器輸出電阻,Rpt 為 PT100 阻值
float Ipt = (3.3f - Vpt) / Rsource; // 計算 PT100 驅(qū)動電流
float Rt = (3.3f - Vpt) / Ipt; // 根據(jù)歐姆定律計算出 PT100 阻值
return Rt;
}
void USART1_Send_Float(float f)
{
char buf[32];
sprintf(buf, "%.1f
", f); // 轉(zhuǎn)換為字符串
while (*buf)
{
USART_SendData(USART1, *buf);
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
buf++;
}
}
int main(void)
{
...
while (1)
{
float Vpt = ADC_Get_Voltage(); // 獲取差分放大器輸出電壓
float Rt = PT100_Get_Rt(Vpt); // 計算 PT100 阻值
float Temp = PT100_Get_Temperature(Rt); // 根據(jù)阻值計算溫度
USART1_Send_Float(Temp); // 將溫度值打印到串口
delay_ms(500);
}
...
}
審核編輯 黃宇
-
OLED
+關(guān)注
關(guān)注
119文章
6171瀏覽量
223683 -
STM32
+關(guān)注
關(guān)注
2264文章
10854瀏覽量
354298 -
熱水器
+關(guān)注
關(guān)注
5文章
213瀏覽量
27041 -
Pt100
+關(guān)注
關(guān)注
9文章
172瀏覽量
69043 -
STM32F103ZET6
+關(guān)注
關(guān)注
9文章
67瀏覽量
21069
發(fā)布評論請先 登錄
相關(guān)推薦
評論