• 方案介紹
    • 一、項目介紹
    • 二、設計流程
    • 三、代碼設計
  • 附件下載
  • 相關推薦
申請入駐 產業(yè)圖譜

基于STM32設計的數顯熱水器

04/16 08:56
802
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

有需要資料的可了解一下.docx

共1個文件

一、項目介紹

當前介紹的項目是基于 STM32F103ZET6 系列 MCU 設計的數顯熱水器,通過顯示屏來顯示熱水器的溫度及其工作狀態(tài),通過 PT100 傳感器來檢測熱水器的溫度變化,并通過電加熱片實現加熱過程,以達到控制熱水器溫度的目的。

image-20230618142512933

image-20230618142039119

二、設計流程

2.1 硬件選型

2.2 軟件設計

(1)顯示屏

使用 OLED 顯示屏來顯示熱水器的溫度及其工作狀態(tài),通過 SPI 接口與 STM32 芯片進行通訊。設計溫度值及其單位、熱水器工作狀態(tài)等。

(2)溫度傳感器

使用 PT100 溫度傳感器來檢測熱水器內部溫度的變化,并將數據通過 ADC 轉換后,傳輸給 STM32 芯片,以實現對熱水器加熱過程的控制。

(3)電加熱片

使用電加熱片模擬熱水器加熱過程,通過繼電器控制電加熱片的通斷,以調節(jié)熱水器的溫度。

(4)控制系統(tǒng)

通過 STM32 芯片來實現對熱水器的控制,讀取溫度傳感器的數據。

三、代碼設計

3.1 OLED顯示屏

(1)SPI 接口初始化

需要對 STM32F103ZET6 的 SPI 接口進行初始化配置,設置相關的時鐘和模式,使其能夠與 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; // 設置 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); // 關閉顯示
    write_command(0xD5); // 設置時鐘分頻因子,震蕩頻率
    write_command(0x80); // 分頻因子=1 ,震蕩頻率(fosc)=8MHz
    write_command(0xA8); // 設置驅動路數:MUX(復用方式)
    write_command(0x1F); // 1/32 duty (0x0F~0x3F)
    write_command(0xD3); // 設置顯示偏移
    write_command(0x00); // 不偏移
    write_command(0x40); // 設置顯示開始行[5:0], 對于設置了32行的液晶,
    // 這里的值為0表示從0行開始顯示
    write_command(0x8D); // 對比度設置
    write_command(0x14); // AHB參考電壓256等分 移位[3:0]100[n,1/256]
    write_command(0x20); // 水平方向上的尋址模式
    write_command(0x00); // 垂直方向上的尋址模式
    write_command(0xA1); // 設置段再映射
    write_command(0xC0); // 設置COM掃描方向
    write_command(0xDA); // 設置COM引腳硬件配置
    write_command(0x12);
    write_command(0x81); // 對比度設置
    write_command(0xBF); // 設置電荷泵電壓
    write_command(0xD9); // 設置預充電周期
    write_command(0xF1);
    write_command(0xDB); // 設置VCOMH電壓倍率
    write_command(0x40);
    write_command(0xAF); // 打開顯示

    OLED_Clear(); // 清屏
}

(3)OLED 顯示函數

接下來編寫 OLED 顯示函數,實現字符和數字的顯示功能。

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)結果顯示

在代碼中調用 OLED_show_string 函數和 OLED_show_char 函數顯示數值和字符。

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 溫度傳感器的引腳設置為輸入模式。

這里以 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); // 設置 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ù)轉換模式
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)溫度轉換函數

根據 PT100 溫度傳感器輸出電壓與溫度的關系,可使用線性函數計算出溫度值。

轉換公式如下:

Rt = (Vref - Vpt) / Ipt // Rt 為 PT100 的阻值,Vref 為基準電壓,Vpt 為 PT100 輸出電壓,Ipt 為 PT100 驅動電流
Temp = a * Rt + b // Temp 為溫度值,a 和 b 為經過擬合后的系數

其中 Rt 的計算需要使用差分運算放大器進行轉換,這里不再贅述。假設已經得到 Rt 值,則溫度轉換函數代碼如下:

float PT100_Get_Temperature(float Rt)
{
    float a = 3.9083e-3f, b = -5.775e-7f, R0 = 100.0f; // 根據實際數據進行擬合得到 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)數據采集

根據差分放大器輸出的電壓值得到 PT100 溫度傳感器的阻值,再根據阻值計算出實際溫度,最后將溫度值通過串口打印出來。以下是數據采集代碼:

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 轉換
    while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)); // 等待轉換結束
    adc_val = ADC_GetConversionValue(ADC1); // 讀取 ADC 轉換結果
    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 驅動電流
    float Rt = (3.3f - Vpt) / Ipt; // 根據歐姆定律計算出 PT100 阻值
    return Rt;
}

void USART1_Send_Float(float f)
{
    char buf[32];
    sprintf(buf, "%.1frn", f); // 轉換為字符串
    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); // 根據阻值計算溫度
        USART1_Send_Float(Temp); // 將溫度值打印到串口
        delay_ms(500);
    }
    ...
}
  • 有需要資料的可了解一下.docx
    下載
意法半導體

意法半導體

意法半導體(ST)集團于1987年6月成立,是由意大利的SGS微電子公司和法國Thomson半導體公司合并而成。1998年5月,SGS-THOMSON Microelectronics將公司名稱改為意法半導體有限公司。意法半導體是世界最大的半導體公司之一,公司銷售收入在半導體工業(yè)五大高速增長市場之間分布均衡(五大市場占2007年銷售收入的百分比):通信(35%),消費(17%),計算機(16%),汽車(16%),工業(yè)(16%)。 據最新的工業(yè)統(tǒng)計數據,意法半導體是全球第五大半導體廠商,在很多市場居世界領先水平。例如,意法半導體是世界第一大專用模擬芯片和電源轉換芯片制造商,世界第一大工業(yè)半導體和機頂盒芯片供應商,而且在分立器件、手機相機模塊和車用集成電路領域居世界前列.

意法半導體(ST)集團于1987年6月成立,是由意大利的SGS微電子公司和法國Thomson半導體公司合并而成。1998年5月,SGS-THOMSON Microelectronics將公司名稱改為意法半導體有限公司。意法半導體是世界最大的半導體公司之一,公司銷售收入在半導體工業(yè)五大高速增長市場之間分布均衡(五大市場占2007年銷售收入的百分比):通信(35%),消費(17%),計算機(16%),汽車(16%),工業(yè)(16%)。 據最新的工業(yè)統(tǒng)計數據,意法半導體是全球第五大半導體廠商,在很多市場居世界領先水平。例如,意法半導體是世界第一大專用模擬芯片和電源轉換芯片制造商,世界第一大工業(yè)半導體和機頂盒芯片供應商,而且在分立器件、手機相機模塊和車用集成電路領域居世界前列.收起

查看更多

相關推薦