国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

STM32 IAP應(yīng)用開發(fā)——通過串口/RS485實(shí)現(xiàn)固件升級(jí)(方式1)

這篇具有很好參考價(jià)值的文章主要介紹了STM32 IAP應(yīng)用開發(fā)——通過串口/RS485實(shí)現(xiàn)固件升級(jí)(方式1)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

STM32 IAP應(yīng)用開發(fā)——通過串口/RS485實(shí)現(xiàn)固件升級(jí)(方式1)

前言

什么是IAP?

IAP(In-Application Programming) 指MCU可以在系統(tǒng)中獲取新代碼并對(duì)自己重新編程,即可用程序來改變程序。在應(yīng)用編程(IAP)是用戶的應(yīng)用代碼對(duì)片內(nèi)Flash存儲(chǔ)器進(jìn)行擦除/編程的方法。這種方式的典型應(yīng)用就是用一小段代碼來實(shí)現(xiàn)程序的下載,實(shí)際上單片機(jī)的ISP功能就是通過IAP技術(shù)來實(shí)現(xiàn)的,即片子在出廠前就已經(jīng)有一段小的boot程序在里面,片子上電后,開始運(yùn)行這段程序,當(dāng)檢測(cè)到上位機(jī)有下載要求時(shí),便和上位機(jī)通信,然后下載數(shù)據(jù)到數(shù)據(jù)存儲(chǔ)區(qū),從而實(shí)現(xiàn)固件升級(jí)。

什么是BootLoader?

百度百科:在嵌入式操作系統(tǒng)中,BootLoader是在操作系統(tǒng)內(nèi)核運(yùn)行之前運(yùn)行??梢猿跏蓟布O(shè)備、建立內(nèi)存空間映射圖,從而將系統(tǒng)的軟硬件環(huán)境帶到一個(gè)合適狀態(tài),以便為最終調(diào)用操作系統(tǒng)內(nèi)核準(zhǔn)備好正確的環(huán)境。在嵌入式系統(tǒng)中,通常并沒有像BIOS那樣的固件程序(注,有的嵌入式CPU也會(huì)內(nèi)嵌一段短小的啟動(dòng)程序),因此整個(gè)系統(tǒng)的加載啟動(dòng)任務(wù)就完全由BootLoader來完成。

實(shí)際上,BootLoader不僅僅在操作系統(tǒng)上使用,在一些內(nèi)存小,功能應(yīng)用較為簡(jiǎn)單的單片機(jī)設(shè)備上面也可以通過BootLoader來完成OTA升級(jí)。

我之前也有發(fā)過一些關(guān)于STM32遠(yuǎn)程升級(jí)的文章,實(shí)現(xiàn)的方式有很多種,感興趣的同學(xué)可以去看一下。
固件升級(jí)系列合集:https://blog.csdn.net/ShenZhen_zixian/article/details/129074047

那么這一期我來介紹一下如何自己制作一個(gè)BootLoader程序,并且通過串口或者RS485實(shí)現(xiàn)固件升級(jí)。

1 環(huán)境搭建

關(guān)于STM32以及Keil的環(huán)境這里就不具體介紹了,網(wǎng)上教程也很多,不懂的同學(xué)自行查閱資料。

2 功能描述

在做bootloader之前一定要先想好升級(jí)的途徑和方式,這樣才好規(guī)劃分區(qū)以及制作bootloader。
關(guān)于bootloader詳細(xì)的講解,可以看下我之前發(fā)的博客:
STM32 IAP應(yīng)用開發(fā)——自制BootLoader

分區(qū)介紹:
我用的是STM32F407,內(nèi)存是512K的(想用內(nèi)存更小的MCU也是可以的,改下各個(gè)分區(qū)的內(nèi)存分配就行了)。
注:F4系列的MCU不像F1那樣,內(nèi)存扇區(qū)都很大(最少也是16K),而且同一塊扇區(qū)只能一起擦除,所以就沒辦法分的那么細(xì)了。詳細(xì)的內(nèi)存分布可以參考下面的兩個(gè)圖。
STM32F4x扇區(qū)分布圖如下:
串口升級(jí)stm32,OTA,單片機(jī)相關(guān),stm32,單片機(jī),嵌入式硬件,OTA
STM32F1x扇區(qū)分布圖如下:
串口升級(jí)stm32,OTA,單片機(jī)相關(guān),stm32,單片機(jī),嵌入式硬件,OTA
那么我這里呢,就用一個(gè)512k的內(nèi)存,分成4個(gè)區(qū)域,來實(shí)現(xiàn)升級(jí)的功能。
分區(qū)表如下:

name offset size function
boot 0x08000000 0x00004000 存放boot程序
setting 0x08004000 0x00004000 存放升級(jí)相關(guān)的配置參數(shù)
app 0x08008000 0x00018000 存放應(yīng)用程序
download 0x08020000 0x00020000 存放需要升級(jí)的新固件

串口升級(jí)stm32,OTA,單片機(jī)相關(guān),stm32,單片機(jī),嵌入式硬件,OTA
方案介紹:
1)bootloader部分:
運(yùn)行時(shí)從setting分區(qū)里面讀取升級(jí)相關(guān)的數(shù)據(jù),確定是否需要升級(jí),如果需要,則把download分區(qū)的固件搬運(yùn)到app分區(qū),如果不需要升級(jí)則直接跳轉(zhuǎn)到app分區(qū)。另外,使用串口1來打印運(yùn)行的一些信息。
2)APP部分:
通過串口2或者RS485連接到PC端,然后等待上位機(jī)發(fā)送特定的升級(jí)命令,如果MCU收到命令,則進(jìn)入下載模式,然后通過串口2或者RS485傳輸新固件到download分區(qū),并且在下載完成后把升級(jí)標(biāo)志寫入到setting分區(qū)里面。
我這里圖方便,串口傳輸固件的方式我采用的是Ymodem協(xié)議,因?yàn)檫@個(gè)協(xié)議很多tool都可以用,就不用專門做一個(gè)上位機(jī)了。如果你想用其他的協(xié)議或者自定義協(xié)議其實(shí)都是可以的,稍做修改就行。

串口升級(jí)stm32,OTA,單片機(jī)相關(guān),stm32,單片機(jī),嵌入式硬件,OTA

3 程序編寫

3.1 BootLoader部分

不管用的是什么MCU,要實(shí)現(xiàn)固件升級(jí)都離不開BootLoader,BootLoader是一個(gè)統(tǒng)稱,它其實(shí)只是一段引導(dǎo)程序,在MCU啟動(dòng)的時(shí)候會(huì)先運(yùn)行這段代碼,判斷是否需要升級(jí),如果不需要升級(jí)就跳轉(zhuǎn)到APP分區(qū)運(yùn)行用戶代碼,如果需要升級(jí)則先通過一些硬件接口接收和搬運(yùn)要升級(jí)的新固件,然后再跳轉(zhuǎn)到APP分區(qū)運(yùn)行新固件,從而實(shí)現(xiàn)固件升級(jí)。
BootLoader的制作需要根據(jù)實(shí)際的需求來做,不同的運(yùn)行方式或者升級(jí)方式在做法上都是有區(qū)別的,包括BootLoader所需要的內(nèi)存空間也不盡相同。
不過不管是用什么方式,Bootloader都應(yīng)該盡可能做的更小更簡(jiǎn)潔,這樣的話內(nèi)存的開銷就更小,對(duì)于內(nèi)存較小的MCU來說壓力就沒那么大了。

示例代碼如下:
分區(qū)定義:

#define FLASH_SECTOR_SIZE           1024
#define FLASH_SECTOR_NUM            512    // 512K
#define FLASH_START_ADDR            ((uint32_t)0x8000000)
#define FLASH_END_ADDR              ((uint32_t)(0x8000000 + FLASH_SECTOR_NUM * FLASH_SECTOR_SIZE))

//flash sector addr
#define ADDR_FLASH_SECTOR_0         ((uint32_t)0x08000000) 	//sector0 addr, 16 Kbytes  
#define ADDR_FLASH_SECTOR_1         ((uint32_t)0x08004000) 	//sector1 addr, 16 Kbytes  
#define ADDR_FLASH_SECTOR_2         ((uint32_t)0x08008000) 	//sector2 addr, 16 Kbytes  
#define ADDR_FLASH_SECTOR_3         ((uint32_t)0x0800C000) 	//sector3 addr, 16 Kbytes  
#define ADDR_FLASH_SECTOR_4         ((uint32_t)0x08010000) 	//sector4 addr, 64 Kbytes  
#define ADDR_FLASH_SECTOR_5         ((uint32_t)0x08020000) 	//sector5 addr, 128 Kbytes  
#define ADDR_FLASH_SECTOR_6         ((uint32_t)0x08040000) 	//sector6 addr, 128 Kbytes  
#define ADDR_FLASH_SECTOR_7         ((uint32_t)0x08060000) 	//sector7 addr, 128 Kbytes  
#define ADDR_FLASH_SECTOR_8         ((uint32_t)0x08080000) 	//sector8 addr, 128 Kbytes  
#define ADDR_FLASH_SECTOR_9         ((uint32_t)0x080A0000) 	//sector9 addr, 128 Kbytes  
#define ADDR_FLASH_SECTOR_10        ((uint32_t)0x080C0000) 	//sector10 addr,128 Kbytes  
#define ADDR_FLASH_SECTOR_11        ((uint32_t)0x080E0000) 	//sector11 addr,128 Kbytes  

#define BOOT_SECTOR_ADDR            0x08000000
#define BOOT_SECTOR_SIZE            0x4000
#define SETTING_SECTOR_ADDR         0x08004000
#define SETTING_SECTOR_SIZE         0x4000
#define APP_SECTOR_ADDR             0x08008000     // APP sector start address  
#define APP_SECTOR_SIZE             0x18000        // APP sector size    
#define DOWNLOAD_SECTOR_ADDR        0x08020000     // Download sector start address
#define DOWNLOAD_SECTOR_SIZE        0x20000        // Download sector size 

程序跳轉(zhuǎn):

uint8_t jump_app(uint32_t app_addr) 
{
    uint32_t jump_addr;
    jump_callback cb;
    if (((*(__IO uint32_t*)app_addr) & 0x2FFE0000 ) == 0x20000000) 
    {  
        jump_addr = *(__IO uint32_t*) (app_addr + 4);  
        cb = (jump_callback)jump_addr;  
        __set_MSP(*(__IO uint32_t*)app_addr);  
        cb();
        return 1;
    } 
    return 0;
}

主函數(shù):

void print_boot_message(void)
{
    uart_log("---------- Enter BootLoader ----------\r\n");
    uart_log("\r\n");
    uart_log("======== flash pration table =========\r\n");
    uart_log("| name     | offset     | size       |\r\n");
    uart_log("--------------------------------------\r\n");
    uart_log("| boot     | 0x08000000 | 0x00004000 |\r\n");
    uart_log("| setting  | 0x08004000 | 0x00004000 |\r\n");
    uart_log("| app      | 0x08008000 | 0x00018000 |\r\n");
    uart_log("| download | 0x08020000 | 0x00020000 |\r\n");
    uart_log("======================================\r\n");
}

int main() 
{
    process_status process;
    uint16_t i;
    uint8_t boot_state;
    uint8_t down_buf[128];
    uint32_t down_addr;
    uint32_t app_addr;

    delay_init(168);
    uart_init(115200);
    print_boot_message();

    boot_parameter.process = read_setting_boot_state();
    boot_parameter.addr = APP_SECTOR_ADDR;

    while (1) 
    {
        process = get_boot_state();
        switch (process) 
        {
            case START_PROGRAM:
                uart_log("start app...\r\n");
                delay_ms(50);
                if (!jump_app(boot_parameter.addr)) 
                {
                    uart_log("no program\r\n");
                    delay_ms(1000);
                }
                uart_log("start app failed\r\n");
                break;
            case UPDATE_PROGRAM:
                uart_log("update app program...\r\n");
                app_addr = APP_SECTOR_ADDR;
                down_addr = DOWNLOAD_SECTOR_ADDR;

                uart_log("app addr: 0x%08X \r\n", app_addr);
                uart_log("down addr: 0x%08X \r\n", down_addr);

                uart_log("erase mcu flash...\r\n");
                mcu_flash_erase(app_addr, APP_ERASE_SECTORS_NUM);  
                uart_log("mcu flash erase success\r\n");
            
                uart_log("write mcu flash...\r\n");
                // memset(down_buf, 0, sizeof(down_buf));
                for (i = 0; i < (APP_SECTOR_SIZE / 1024) * 8; i++)
                {
                    mcu_flash_read(down_addr, &down_buf[0], 128);
                    delay_ms(5);
                    mcu_flash_write(app_addr, &down_buf[0], 128);
                    delay_ms(5);
                    down_addr += 128;
                    app_addr += 128;
                    // uart_log("mcu_flash_write: %d\r\n", i);
                }
                uart_log("mcu flash write success\r\n");

                set_boot_state(UPDATE_SUCCESS);
                break;
            case UPDATE_SUCCESS:
                uart_log("update success\r\n");
                boot_state = UPDATE_SUCCESS_STATE;
                write_setting_boot_state(boot_state);
                set_boot_state(START_PROGRAM);
                break;
            default:
                break;
        }
    }
}

關(guān)于bootloader詳細(xì)的講解,可以看下我之前發(fā)的博客:
STM32 IAP應(yīng)用開發(fā)——自制BootLoader
完整代碼下載地址:https://download.csdn.net/download/ShenZhen_zixian/87546126

3.2 APP的制作

APP部分根據(jù)自己實(shí)際的功能來做,我這里用的是串口或者RS485連接PC端,然后傳輸固件的協(xié)議用的是Ymodem。
當(dāng)然了,協(xié)議也是可以自定義,只要能正確的把固件從PC端搬運(yùn)到MCU的flash就行了。

示例代碼如下:
Ymodem協(xié)議部分:
注:詳細(xì)的協(xié)議解析這里就不講解了,不懂的同學(xué)自行查閱資料。

void ymodem_ack(void) 
{
    uint8_t buf;
    buf = YMODEM_ACK;
    RS485_Send_Data(&buf, 1);
}

void ymodem_nack(void) 
{
    uint8_t buf;
    buf = YMODEM_NAK;
    RS485_Send_Data(&buf, 1);
}

void ymodem_c(void) 
{
    uint8_t buf;
    buf = YMODEM_C;
    RS485_Send_Data(&buf, 1);
}

void set_ymodem_status(process_status process) 
{
    ymodem.process = process;
}

process_status get_ymodem_status(void) 
{
    process_status process = ymodem.process;
    return process;
}

void ymodem_start(ymodem_callback cb) 
{
    if (ymodem.status == 0) 
    {
        ymodem.cb = cb;
    }
}

void ymodem_recv(download_buf_t *p) 
{
    uint8_t type = p->data[0];
    switch (ymodem.status) 
    {
        case 0:
            if (type == YMODEM_SOH) 
            {
                ymodem.process = BUSY;
                ymodem.addr = DOWNLOAD_SECTOR_ADDR;
                mcu_flash_erase(ymodem.addr, ERASE_SECTORS);
                ymodem_ack();
                ymodem_c();
                ymodem.status++;
            }
            else if (type == '1') 
            {
                uart_log("enter update mode\r\n");
                ymodem.process = UPDATE_PROGRAM;
            }
            break;
        case 1:
            if (type == YMODEM_SOH || type == YMODEM_STX) 
            {
                if (type == YMODEM_SOH) 
                {
                    mcu_flash_write(ymodem.addr, &p->data[3], 128);
                    ymodem.addr += 128;
                }
                else 
                {
                    mcu_flash_write(ymodem.addr, &p->data[3], 1024);
                    ymodem.addr += 1024;
                }
                ymodem_ack();
            }
            else if (type == YMODEM_EOT) 
            {
                ymodem_nack();
                ymodem.status++;
            }
            else 
            {
                ymodem.status = 0;
            }
            break;
        case 2:
            if (type == YMODEM_EOT) 
            {
                ymodem_ack();
                ymodem_c();
                ymodem.status++;
            }
            break;
        case 3:
            if (type == YMODEM_SOH) 
            {
                ymodem_ack();
                ymodem.status = 0;
                ymodem.process = UPDATE_SUCCESS;
            }
    }
    p->len = 0;
}

void ymodem_handle(void)
{
    uint8_t boot_state;
    process_status process;

    process = get_ymodem_status();
    switch (process) 
    {
        case START_PROGRAM:
            break;
        case UPDATE_PROGRAM:
            ymodem_c();
            delay_ms(1000);
            break;
        case UPDATE_SUCCESS:
            boot_state = UPDATE_PROGRAM_STATE;
            mcu_flash_erase(SETTING_BOOT_STATE, 1);
            mcu_flash_write(SETTING_BOOT_STATE, &boot_state, 1);
            // mcu_flash_read(SETTING_BOOT_STATE, &boot_state, 1);
            // uart_log("boot_state:%d\r\n", boot_state);
            uart_log("firmware download success\r\n");
            uart_log("system reboot...\r\n");
            delay_ms(2000);
            system_reboot();
            break;
        default:
            break;
    }
}

void ymodem_init(void)
{
    RS485_Init(115200);
    timer_init();
    queue_initiate(&rx_queue);
}

主函數(shù):

#define APP_VERSION   "V100"

void print_boot_message(void)
{
    uart_log("======================================\r\n");
    uart_log("-------------- Enter APP -------------\r\n");
    uart_log ("app version is: %s\r\n", APP_VERSION);
    uart_log("======================================\r\n");
}

int main(void)
{
    delay_init(168);
    uart_init(115200);
    ymodem_init();
    print_boot_message();
    
    uart_log ("app init success\r\n");
    while (1)
    {
        ymodem_handle();
    }
}

修改中斷向量:
bootloader的運(yùn)行地址是在起始地址上的,所以中斷向量是0,不用改。
但是app的運(yùn)行地址是在起始地址上做了偏移的,所以中斷向量也要改,不然會(huì)運(yùn)行會(huì)出問題。

#define VECT_TAB_OFFSET  0x8000

注:這個(gè)變量定義在system_stm32f4xx.c中可以找到。

完整代碼下載地址:https://download.csdn.net/download/ShenZhen_zixian/87546126

4 修改工程中的內(nèi)存配置

因?yàn)槲覀儗?duì)stm32的內(nèi)存進(jìn)行了分區(qū),不同的代碼要存放在不同的區(qū)域,因此,我們?cè)诰幾g工程之前需要先定義好各自的區(qū)域,以免出現(xiàn)內(nèi)存越界。

4.1 Bootloader工程內(nèi)存配置

Bootloader的起始地址不需要改,按flash默認(rèn)地址即可,size需要改成實(shí)際分區(qū)大小。

串口升級(jí)stm32,OTA,單片機(jī)相關(guān),stm32,單片機(jī),嵌入式硬件,OTA

4.2 APP工程內(nèi)存配置

APP的起始地址和size都需要根據(jù)實(shí)際的分區(qū)來改。
串口升級(jí)stm32,OTA,單片機(jī)相關(guān),stm32,單片機(jī),嵌入式硬件,OTA

5 燒錄相關(guān)配置

我們的Bootloader做好以后需要燒錄到MCU里面,可以直接用Keil uVison來下載,也可以用J-Flash或者其他,這個(gè)都沒關(guān)系,但是要注意內(nèi)存的分配,要把固件燒到對(duì)應(yīng)的內(nèi)存地址上。

5.1 BootLoader部分

1)使用Keil uVision下載
如果是用keil下載的話,需要注意flash的配置,具體如下:
串口升級(jí)stm32,OTA,單片機(jī)相關(guān),stm32,單片機(jī),嵌入式硬件,OTA
2)使用其他下載工具
如果是用J-Flash或者STlink的工具燒錄的話注意燒錄的起始地址是0x08000000就好了。

5.2 APP部分

1)使用Keil uVision下載
跟BootLoader一樣,我們按照前面分配好的空間配置APP的參數(shù)即可。
串口升級(jí)stm32,OTA,單片機(jī)相關(guān),stm32,單片機(jī),嵌入式硬件,OTA
2)使用其他下載工具
如果是用J-Flash或者STlink的工具燒錄的話注意燒錄的起始地址是0x08008000就好了。

6 運(yùn)行測(cè)試

用串口助手查看運(yùn)行l(wèi)og(我這里用的是XShell,用其他的也是可以的)。

1)開始運(yùn)行代碼
不需要升級(jí)時(shí)直接跳轉(zhuǎn)到App區(qū),如下圖:
串口升級(jí)stm32,OTA,單片機(jī)相關(guān),stm32,單片機(jī),嵌入式硬件,OTA

2)進(jìn)入燒錄模式
進(jìn)入APP之后,往串口2/RS485發(fā)送一個(gè)字符"1",進(jìn)入升級(jí)模式,然后通過調(diào)試工具發(fā)送新固件的bin文件。
注:為了方便調(diào)試才用了一個(gè)字符"1",實(shí)際使用的話最好改一下,太簡(jiǎn)單的話容易出現(xiàn)誤操作。
串口調(diào)試窗口log如下圖:
串口升級(jí)stm32,OTA,單片機(jī)相關(guān),stm32,單片機(jī),嵌入式硬件,OTA

3)通過Ymodem傳輸新固件
調(diào)試工具我用的是XShell,實(shí)際上用其他工具也行,只要支持Ymodem方式傳輸文件即可。
串口升級(jí)stm32,OTA,單片機(jī)相關(guān),stm32,單片機(jī),嵌入式硬件,OTA串口升級(jí)stm32,OTA,單片機(jī)相關(guān),stm32,單片機(jī),嵌入式硬件,OTA
4)升級(jí)固件
固件搬運(yùn)完成后自動(dòng)重啟,重新運(yùn)行Bootloader,然后進(jìn)行固件的升級(jí)。
串口升級(jí)stm32,OTA,單片機(jī)相關(guān),stm32,單片機(jī),嵌入式硬件,OTA
至此,整個(gè)升級(jí)流程就走完了。

結(jié)束語(yǔ)

好了,關(guān)于自制BootLoader并實(shí)現(xiàn)串口和RS485在線升級(jí)的介紹就講到這里,本文列舉的例子其實(shí)只是升級(jí)的其中一種方式,只是提供一個(gè)思路,不是唯一的方法,實(shí)際上最好還是根據(jù)自己實(shí)際的需求來做。
需要源碼的同學(xué)可以在下面的鏈接下載,我把BootLoader和APP都上傳了。
如果你有什么問題或者有更好的方法,歡迎在評(píng)論區(qū)留言。

完整代碼下載地址:https://download.csdn.net/download/ShenZhen_zixian/87546126
更多相關(guān)文章:
固件升級(jí)系列合集:https://blog.csdn.net/ShenZhen_zixian/article/details/129074047文章來源地址http://www.zghlxwxcb.cn/news/detail-690097.html

到了這里,關(guān)于STM32 IAP應(yīng)用開發(fā)——通過串口/RS485實(shí)現(xiàn)固件升級(jí)(方式1)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • STM32CubeIDE開發(fā)(二十二), stm32的RS485/232串口通信開發(fā)要點(diǎn)

    STM32CubeIDE開發(fā)(二十二), stm32的RS485/232串口通信開發(fā)要點(diǎn)

    目錄 一、stm32串口通信 ??????? 1.1 硬件流控 ???????? 1.2 軟件流控 ??????? 1.3 串口通信參數(shù) 二、新建RS485通信工程 ??????? 2.1 項(xiàng)目實(shí)現(xiàn)背景信息 ??????? 2.2 項(xiàng)目配置 ??????? 2.3 代碼實(shí)現(xiàn) ?? 三、RS485驅(qū)動(dòng)調(diào)用及測(cè)試 ??????? 3.1 接口調(diào)用 ?????? 3.2 編

    2024年01月20日
    瀏覽(80)
  • STM32 IAP應(yīng)用開發(fā)——自制BootLoader

    STM32 IAP應(yīng)用開發(fā)——自制BootLoader

    什么是IAP? IAP(In-Application Programming) 指MCU可以在系統(tǒng)中獲取新代碼并對(duì)自己重新編程,即可用程序來改變程序。在應(yīng)用編程(IAP)是用戶的應(yīng)用代碼對(duì)片內(nèi)Flash存儲(chǔ)器進(jìn)行擦除/編程的方法。這種方式的典型應(yīng)用就是用一小段代碼來實(shí)現(xiàn)程序的下載,實(shí)際上單片機(jī)的ISP功能就

    2024年02月13日
    瀏覽(23)
  • STM32 IAP應(yīng)用開發(fā)--bootloader升級(jí)程序

    STM32 IAP應(yīng)用開發(fā)--bootloader升級(jí)程序

    原文鏈接:https://blog.csdn.net/ShenZhen_zixian/article/details/129424077 什么是IAP? IAP(In-Application Programming) 指MCU可以在系統(tǒng)中獲取新代碼并對(duì)自己重新編程,即可用程序來改變程序。在應(yīng)用編程(IAP)是用戶的應(yīng)用代碼對(duì)片內(nèi)Flash存儲(chǔ)器進(jìn)行擦除/編程的方法。這種方式的典型應(yīng)用就

    2024年01月17日
    瀏覽(18)
  • STM32之485通信(RS485串口編程)

    目錄 1.編程思路 2.代碼? ? USART串口的庫(kù)函數(shù): ???USART_: ? ? ? AIRCR中斷分組設(shè)置表:? ? ? ? ? ? 通過485通信來實(shí)現(xiàn)MCU之間的通信,把接收到的數(shù)據(jù)通過串口助手顯示在pc端。第一是對(duì)usart1,usart2進(jìn)行初始化,Usart1負(fù)責(zé)與串口助手通信,Usart2,485負(fù)責(zé)進(jìn)行MCU通信。第二是

    2024年01月18日
    瀏覽(79)
  • 調(diào)試筆記-stm32的OTA/IAP 通過485升級(jí)固件

    調(diào)試筆記-stm32的OTA/IAP 通過485升級(jí)固件

    背景:最近需要在stm32上實(shí)現(xiàn)通過rs485升級(jí)固件功能。經(jīng)過幾天搜索和調(diào)試,實(shí)現(xiàn)了功能。 目標(biāo):使用cubeIDE實(shí)現(xiàn)stm32F407VGT6,通過RS485升級(jí)固件 調(diào)試記錄: 步驟1. 在keil環(huán)境下的rs485升級(jí)固件(含源碼):STM32 OTA應(yīng)用開發(fā)——通過串口/RS485實(shí)現(xiàn)OTA升級(jí)(方式2)_stm32串口升級(jí)_柒壹漆

    2024年02月11日
    瀏覽(21)
  • 【正點(diǎn)原子STM32】RS485串行通信標(biāo)準(zhǔn)(串口基礎(chǔ)協(xié)議 和 MODBUS協(xié)議、總線連接、通信電路、通信波形圖、RS485相關(guān)HAL庫(kù)驅(qū)動(dòng)、RS485配置步驟、)

    【正點(diǎn)原子STM32】RS485串行通信標(biāo)準(zhǔn)(串口基礎(chǔ)協(xié)議 和 MODBUS協(xié)議、總線連接、通信電路、通信波形圖、RS485相關(guān)HAL庫(kù)驅(qū)動(dòng)、RS485配置步驟、)

    一、RS485介紹 二、RS485相關(guān)HAL庫(kù)驅(qū)動(dòng)介紹 三、RS485配置步驟 四、編程實(shí)戰(zhàn) 五、總結(jié) 串口、UART、TTL、RS232、RS422和RS485之間的關(guān)系可以如此理解: 串口 :是一個(gè)廣義術(shù)語(yǔ),通常指的是采用串行通信協(xié)議的接口,它可以包括多種具體的物理接口標(biāo)準(zhǔn)和邏輯電平標(biāo)準(zhǔn)。 UART (通用

    2024年04月13日
    瀏覽(30)
  • # 項(xiàng)目一:???STM32+串口DMA+RS485+MODBUS+傳感器實(shí)現(xiàn)SO2的測(cè)試

    # 項(xiàng)目一:???STM32+串口DMA+RS485+MODBUS+傳感器實(shí)現(xiàn)SO2的測(cè)試

    通過STM32控制傳感器實(shí)現(xiàn)氣體濃度的測(cè)量:RS485+MODBUS+串口DMA+定時(shí)器。 其中,USART2負(fù)責(zé)控制數(shù)據(jù)的發(fā)送和接受,USART3負(fù)責(zé)將詢問幀、應(yīng)答幀以及處理后數(shù)據(jù)打印出來,TIM1負(fù)責(zé)每隔1秒發(fā)送一次詢問幀。 持續(xù)更新手中的項(xiàng)目(導(dǎo)師給的活)經(jīng)驗(yàn)。。。 打工人加油??????????

    2024年02月11日
    瀏覽(26)
  • STM32開發(fā)(六)STM32F103 通信 —— RS485 Modbus通信編程詳解

    STM32開發(fā)(六)STM32F103 通信 —— RS485 Modbus通信編程詳解

    ??《上一篇》 ???《主目錄》 ???《下一篇》 了解 RS485 Modbus協(xié)議技術(shù) 。本實(shí)驗(yàn)是基于STM32F103開發(fā) 實(shí)現(xiàn) 通過RS-485實(shí)現(xiàn)modbus協(xié)議。 準(zhǔn)備好了嗎?開始我的show time。 1、硬件開發(fā)準(zhǔn)備 主控:STM32F103ZET6 RS485收發(fā)器:SP3485P 2、軟件開發(fā)準(zhǔn)備 軟件開發(fā)使用虛擬機(jī) + VScode + STM32Cub

    2024年02月03日
    瀏覽(25)
  • 基于STM32單片機(jī)BOOTLOADER通過串口升級(jí)程序IAP——APP方案

    基于STM32單片機(jī)BOOTLOADER通過串口升級(jí)程序IAP——APP方案

    ????????????????????????此方法前提是你得有一個(gè)EEPROM ? ? ? ? 我用的單片機(jī)是STM32F103ZET6 , 此單片機(jī)FLASH容量為512KB; 在此單片機(jī)里面FLASH的起始地址是0X8000000,BOOT作為引導(dǎo)加載程序一般都是從這個(gè)地址開始,單片機(jī)一上點(diǎn)默認(rèn)會(huì)從這個(gè)地址開始運(yùn)行,所以將自己

    2024年02月04日
    瀏覽(96)
  • STM32F429 Discovery開發(fā)板應(yīng)用:使用FreeRTOS隊(duì)列+DMA雙緩存實(shí)現(xiàn)串口數(shù)據(jù)接收

    STM32F429 Discovery開發(fā)板應(yīng)用:使用FreeRTOS隊(duì)列+DMA雙緩存實(shí)現(xiàn)串口數(shù)據(jù)接收

    ? 參考帖子:https://blog.csdn.net/freedompoi/article/details/122350866 目前想要實(shí)現(xiàn)STM32F4自帶的DMA雙緩沖區(qū),嘗試過一版,結(jié)果不能預(yù)期,就使用了RxHalfCplt和RxCplt去實(shí)現(xiàn)DMA雙緩沖區(qū)的效果。 現(xiàn)在有時(shí)間了,又重新實(shí)現(xiàn)STM32F4自帶的DMA雙緩沖區(qū),作為參考。 ? MCU:STM32F429ZIT6 開發(fā)環(huán)境:

    2024年02月08日
    瀏覽(23)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包