日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

正点原子STM32

發布時間:2023/12/10 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 正点原子STM32 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

正點原子B站視頻地址:https://www.bilibili.com/video/BV1Lx411Z7Qa?p=4&spm_id_from=pageDriver

目錄

  • STM32命名規則
  • STM32芯片解讀
  • 開發環境搭建(MDK - 就是ARM的keil,需破解 + 支持包 + CH340串口驅動+ JLINK驅動)
  • 程序下載方法 (ISP串口下載 + JLINK下載更方便)
  • 新建工程模板——基于固件庫
  • 新建工程模板——基于寄存器
  • GPIO相關配置寄存器
  • 端口復用、重映射、中斷
  • JLINK在線調試
    • JTAG/SWD調試原理
    • 軟件仿真
    • ST-LINK下載與調試程序(硬件)
  • 獨立看門狗IWDG
    • 獨立看門狗概述
    • 寄存器和庫函數
    • 代碼實現
  • 窗口看門狗WWDG
    • 窗口看門狗概述
    • 寄存器和庫函數
    • 代碼實現
  • 2.4G無線射頻通信模塊
    • NRF24L01簡介
    • 寄存器介紹
    • 硬件連接
    • 源碼講解
  • 485通信實驗
    • 485接口原理
  • FLASH模擬EEPROM
    • FLASH介紹
    • FLASH操作(讀、寫、擦除)
    • 寄存器
    • 常用庫函數
    • 程序編寫
  • 串口IAP實驗(在程序中編程In Application Programming)
    • STM32IAP介紹
    • IAP運作流程
    • IAP配置
    • 實驗程序
      • APP 程序起始地址設置方法
      • 中斷向量表的偏移量設置方法
  • 藍牙模塊HC05使用
    • 模塊介紹
    • 模塊AT指令集
    • **與上位機串口通信**
    • **與手機藍牙調試助手通信**
    • 與單片機連接通信

STM32命名規則

STM32芯片解讀








開發環境搭建(MDK - 就是ARM的keil,需破解 + 支持包 + CH340串口驅動+ JLINK驅動)


上圖在MDK環境中點擊下載即可,或者去官網下載:


程序下載方法 (ISP串口下載 + JLINK下載更方便)

ISP串口下載

以前學習的是電腦USB端連接CH340芯片。

正點原子還設計了一鍵下載電路,不用來回撥動跳線帽。





JLINK程序下載

需要先安裝JLINK驅動,前面講過了

在MDK中配置一下JLINK





新建工程模板——基于固件庫

視頻開發環境:MDK5
固件庫版本:V3.5

解壓正點原子文件夾內的固件庫包–C:\Users\朱冠霖\Desktop\【正點原子】戰艦STM32F103開發板\【正點原子】戰艦STM32F103開發板資料 資料盤(A盤)\8,STM32參考資料\1,STM32F1xx固件庫

新建工程模板——基于寄存器

GPIO相關配置寄存器






端口復用、重映射、中斷


JLINK在線調試

JTAG/SWD調試原理



軟件仿真

ST-LINK下載與調試程序(硬件)

獨立看門狗IWDG

獨立看門狗概述


寄存器和庫函數





上圖prer表示預分屏值

代碼實現

wdg.h

#ifndef __WDG_H #define __WDG_H #include "sys.h"void IWDG_Init(u8 prer,u16 rlr); void IWDG_Feed(void);#endif

wdg.c

#include "wdg.h"//初始化獨立看門狗 //prer:分頻數:0~7(只有低3位有效!) //分頻因子=4*2^prer.但最大值只能是256! //rlr:重裝載寄存器值:低11位有效. //時間計算(大概):Tout=((4*2^prer)*rlr)/40 (ms). void IWDG_Init(u8 prer,u16 rlr) { IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //使能對寄存器IWDG_PR和IWDG_RLR的寫操作(取消寫保護)IWDG_SetPrescaler(prer); //設置IWDG預分頻值:設置IWDG預分頻值為64IWDG_SetReload(rlr); //設置IWDG重裝載值rlrIWDG_ReloadCounter(); //按照IWDG重裝載寄存器的值rlr重裝載IWDG計數器IWDG_Enable(); //使能IWDG } //喂獨立看門狗 void IWDG_Feed(void) { IWDG_ReloadCounter();//reload }

main.c

#include "led.h" #include "delay.h" #include "key.h" #include "sys.h" #include "usart.h" #include "wdg.h"int main(void) { delay_init(); //延時函數初始化 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //設置NVIC中斷分組2:2位搶占優先級,2位響應優先級uart_init(115200); //串口初始化為115200LED_Init(); //初始化與LED連接的硬件接口KEY_Init(); //按鍵初始化 delay_ms(500); //讓人看得到滅IWDG_Init(4,625); //預分頻數為64,重載值為625,溢出時間為1s LED0=0; //點亮LED0while(1){if(KEY_Scan(0)==WKUP_PRES){ //調用函數IWDG_ReloadCounter()一樣的 IWDG_Feed();//如果WK_UP按下,則喂狗,燈一直亮 不喂狗則程序一直復位燈一直閃爍}delay_ms(10);}; }

窗口看門狗WWDG

窗口看門狗概述




寄存器和庫函數



代碼實現

wdg.h

#ifndef __WDG_H #define __WDG_H #include "sys.h"void IWDG_Init(u8 prer,u16 rlr); void IWDG_Feed(void);void WWDG_Init(u8 tr,u8 wr,u32 fprer);//初始化WWDG void WWDG_Set_Counter(u8 cnt); //設置WWDG的計數器 void WWDG_NVIC_Init(void); #endif

wdg.c

#include "wdg.h" #include "led.h"void IWDG_Init(u8 prer,u16 rlr) { IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //使能對寄存器IWDG_PR和IWDG_RLR的寫操作IWDG_SetPrescaler(prer); //設置IWDG預分頻值:設置IWDG預分頻值為64IWDG_SetReload(rlr); //設置IWDG重裝載值IWDG_ReloadCounter(); //按照IWDG重裝載寄存器的值重裝載IWDG計數器 IWDG_Enable(); //使能IWDG } //喂獨立看門狗 void IWDG_Feed(void) { IWDG_ReloadCounter(); //重載計數值 }//保存WWDG計數器的設置值,默認為最大. u8 WWDG_CNT=0x7f; //初始化窗口看門狗 //tr :T[6:0],計數器值 往下計數 //wr :W[6:0],窗口值 //fprer:分頻系數(WDGTB),僅最低2位有效 //Fwwdg=PCLK1/(4096*2^fprer). void WWDG_Init(u8 tr,u8 wr,u32 fprer) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE); // WWDG時鐘使能WWDG_CNT=tr&WWDG_CNT; //初始化WWDG_CNT. 與運算取后7位 WWDG_SetPrescaler(fprer);設置IWDG預分頻值WWDG_SetWindowValue(wr);//設置窗口值WWDG_Enable(WWDG_CNT); //使能看門狗 , 設置 counter . WWDG_ClearFlag();//清除提前喚醒中斷標志位 WWDG_NVIC_Init();//初始化窗口看門狗 NVICWWDG_EnableIT(); //開啟窗口看門狗中斷 } //重設置WWDG計數器的值 void WWDG_Set_Counter(u8 cnt) {WWDG_Enable(cnt);//使能看門狗 , 設置 counter . }//窗口看門狗中斷服務程序 void WWDG_NVIC_Init() {NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn; //WWDG中斷NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //搶占2,子優先級3,組2 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //搶占2,子優先級3,組2 NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; NVIC_Init(&NVIC_InitStructure);//NVIC初始化 }void WWDG_IRQHandler(void){WWDG_SetCounter(WWDG_CNT);//喂狗 當禁掉此句后,窗口看門狗將產生復位WWDG_ClearFlag(); //清除提前喚醒中斷標志位LED1=!LED1; //LED1狀態翻轉(指示喂狗成功)}

main.c

#include "led.h" #include "delay.h" #include "key.h" #include "sys.h" #include "usart.h" #include "wdg.h"int main(void){ delay_init(); //延時函數初始化 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//設置中斷優先級分組為組2:2位搶占優先級,2位響應優先級uart_init(115200); //串口初始化為115200LED_Init();KEY_Init(); //按鍵初始化 LED0=0;delay_ms(300); //計數器從0x7F到0x40,觸發中斷喂狗,LED1燈翻轉WWDG_Init(0X7F,0X5F,WWDG_Prescaler_8);//計數器值為7f,上窗口寄存器為5f(下窗口固定),分頻數為8 while(1){LED0=1; } }

2.4G無線射頻通信模塊

NRF24L01簡介











寄存器介紹










硬件連接


源碼講解


24101.h

#ifndef __24L01_H #define __24L01_H #include "sys.h" // //本程序只供學習使用,未經作者許可,不得用于其它任何用途 //ALIENTEK戰艦STM32開發板V3 //NRF24L01驅動代碼 //正點原子@ALIENTEK //技術論壇:www.openedv.com //創建日期:2015/1/17 //版本:V1.0 //版權所有,盜版必究。 //Copyright(C) 廣州市星翼電子科技有限公司 2009-2019 //All rights reserved //// //NRF24L01寄存器操作命令 #define NRF_READ_REG 0x00 //讀配置寄存器,低5位為寄存器地址 #define NRF_WRITE_REG 0x20 //寫配置寄存器,低5位為寄存器地址 #define RD_RX_PLOAD 0x61 //讀RX有效數據,1~32字節 #define WR_TX_PLOAD 0xA0 //寫TX有效數據,1~32字節 #define FLUSH_TX 0xE1 //清除TX FIFO寄存器.發射模式下用 #define FLUSH_RX 0xE2 //清除RX FIFO寄存器.接收模式下用 #define REUSE_TX_PL 0xE3 //重新使用上一包數據,CE為高,數據包被不斷發送. #define NOP 0xFF //空操作,可以用來讀狀態寄存器 //SPI(NRF24L01)寄存器地址 #define CONFIG 0x00 //配置寄存器地址;bit0:1接收模式,0發射模式;bit1:電選擇;bit2:CRC模式;bit3:CRC使能;//bit4:中斷MAX_RT(達到最大重發次數中斷)使能;bit5:中斷TX_DS使能;bit6:中斷RX_DR使能 #define EN_AA 0x01 //使能自動應答功能 bit0~5,對應通道0~5 #define EN_RXADDR 0x02 //接收地址允許,bit0~5,對應通道0~5 #define SETUP_AW 0x03 //設置地址寬度(所有數據通道):bit1,0:00,3字節;01,4字節;02,5字節; #define SETUP_RETR 0x04 //建立自動重發;bit3:0,自動重發計數器;bit7:4,自動重發延時 250*x+86us #define RF_CH 0x05 //RF通道,bit6:0,工作通道頻率; #define RF_SETUP 0x06 //RF寄存器;bit3:傳輸速率(0:1Mbps,1:2Mbps);bit2:1,發射功率;bit0:低噪聲放大器增益 #define STATUS 0x07 //狀態寄存器;bit0:TX FIFO滿標志;bit3:1,接收數據通道號(最大:6);bit4,達到最多次重發//bit5:數據發送完成中斷;bit6:接收數據中斷; #define MAX_TX 0x10 //達到最大發送次數中斷 #define TX_OK 0x20 //TX發送完成中斷 #define RX_OK 0x40 //接收到數據中斷#define OBSERVE_TX 0x08 //發送檢測寄存器,bit7:4,數據包丟失計數器;bit3:0,重發計數器 #define CD 0x09 //載波檢測寄存器,bit0,載波檢測; #define RX_ADDR_P0 0x0A //數據通道0接收地址,最大長度5個字節,低字節在前 #define RX_ADDR_P1 0x0B //數據通道1接收地址,最大長度5個字節,低字節在前 #define RX_ADDR_P2 0x0C //數據通道2接收地址,最低字節可設置,高字節,必須同RX_ADDR_P1[39:8]相等; #define RX_ADDR_P3 0x0D //數據通道3接收地址,最低字節可設置,高字節,必須同RX_ADDR_P1[39:8]相等; #define RX_ADDR_P4 0x0E //數據通道4接收地址,最低字節可設置,高字節,必須同RX_ADDR_P1[39:8]相等; #define RX_ADDR_P5 0x0F //數據通道5接收地址,最低字節可設置,高字節,必須同RX_ADDR_P1[39:8]相等; #define TX_ADDR 0x10 //發送地址(低字節在前),ShockBurstTM模式下,RX_ADDR_P0與此地址相等 #define RX_PW_P0 0x11 //接收數據通道0有效數據寬度(1~32字節),設置為0則非法 #define RX_PW_P1 0x12 //接收數據通道1有效數據寬度(1~32字節),設置為0則非法 #define RX_PW_P2 0x13 //接收數據通道2有效數據寬度(1~32字節),設置為0則非法 #define RX_PW_P3 0x14 //接收數據通道3有效數據寬度(1~32字節),設置為0則非法 #define RX_PW_P4 0x15 //接收數據通道4有效數據寬度(1~32字節),設置為0則非法 #define RX_PW_P5 0x16 //接收數據通道5有效數據寬度(1~32字節),設置為0則非法 #define NRF_FIFO_STATUS 0x17 //FIFO狀態寄存器;bit0,RX FIFO寄存器空標志;bit1,RX FIFO滿標志;bit2,3,保留//bit4,TX FIFO空標志;bit5,TX FIFO滿標志;bit6,1,循環發送上一數據包.0,不循環; // //24L01操作線 #define NRF24L01_CE PGout(8) //24L01片選信號 #define NRF24L01_CSN PGout(7) //SPI片選信號 #define NRF24L01_IRQ PGin(6) //IRQ主機數據輸入 //24L01發送接收數據寬度定義 #define TX_ADR_WIDTH 5 //5字節的地址寬度 #define RX_ADR_WIDTH 5 //5字節的地址寬度 #define TX_PLOAD_WIDTH 32 //32字節的用戶數據寬度 #define RX_PLOAD_WIDTH 32 //32字節的用戶數據寬度void NRF24L01_Init(void); //初始化 void NRF24L01_RX_Mode(void); //配置為接收模式 void NRF24L01_TX_Mode(void); //配置為發送模式 u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 u8s);//寫數據區 u8 NRF24L01_Read_Buf(u8 reg, u8 *pBuf, u8 u8s); //讀數據區 u8 NRF24L01_Read_Reg(u8 reg); //讀寄存器 u8 NRF24L01_Write_Reg(u8 reg, u8 value); //寫寄存器 u8 NRF24L01_Check(void); //檢查24L01是否存在 u8 NRF24L01_TxPacket(u8 *txbuf); //發送一個包的數據 u8 NRF24L01_RxPacket(u8 *rxbuf); //接收一個包的數據 #endif

24101.c

#include "24l01.h" #include "lcd.h" #include "delay.h" #include "spi.h" #include "usart.h" // //本程序只供學習使用,未經作者許可,不得用于其它任何用途 //ALIENTEK戰艦STM32開發板 //NRF24L01驅動代碼 //正點原子@ALIENTEK //技術論壇:www.openedv.com //修改日期:2012/9/13 //版本:V1.0 //版權所有,盜版必究。 //Copyright(C) 廣州市星翼電子科技有限公司 2009-2019 //All rights reserved //const u8 TX_ADDRESS[TX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01}; //發送地址 const u8 RX_ADDRESS[RX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01};//初始化24L01的IO口 void NRF24L01_Init(void) { GPIO_InitTypeDef GPIO_InitStructure;SPI_InitTypeDef SPI_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOG, ENABLE); //使能PB,G端口時鐘GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //PB12上拉 防止W25X的干擾GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽輸出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化指定IOGPIO_SetBits(GPIOB,GPIO_Pin_12);//上拉 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7|GPIO_Pin_8; //PG8 7 推挽 GPIO_Init(GPIOG, &GPIO_InitStructure);//初始化指定IOGPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PG6 輸入 GPIO_Init(GPIOG, &GPIO_InitStructure);GPIO_ResetBits(GPIOG,GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8);//PG6,7,8上拉 SPI2_Init(); //初始化SPI SPI_Cmd(SPI2, DISABLE); // SPI外設不使能SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //SPI設置為雙線雙向全雙工SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //SPI主機SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //發送接收8位幀結構SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //時鐘懸空低SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //數據捕獲于第1個時鐘沿SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信號由軟件控制SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; //定義波特率預分頻的值:波特率預分頻值為16SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //數據傳輸從MSB位開始SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值計算的多項式SPI_Init(SPI2, &SPI_InitStructure); //根據SPI_InitStruct中指定的參數初始化外設SPIx寄存器SPI_Cmd(SPI2, ENABLE); //使能SPI外設NRF24L01_CE=0; //使能24L01NRF24L01_CSN=1; //SPI片選取消 } //檢測24L01是否存在 //返回值:0,成功;1,失敗 u8 NRF24L01_Check(void) {u8 buf[5]={0XA5,0XA5,0XA5,0XA5,0XA5};u8 i;SPI2_SetSpeed(SPI_BaudRatePrescaler_4); //spi速度為9Mhz(24L01的最大SPI時鐘為10Mhz) NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,buf,5);//寫入5個字節的地址. NRF24L01_Read_Buf(TX_ADDR,buf,5); //讀出寫入的地址 for(i=0;i<5;i++)if(buf[i]!=0XA5)break; if(i!=5)return 1;//檢測24L01錯誤 return 0; //檢測到24L01 } //SPI寫寄存器 //reg:指定寄存器地址 //value:寫入的值 u8 NRF24L01_Write_Reg(u8 reg,u8 value) {u8 status; NRF24L01_CSN=0; //使能SPI傳輸status =SPI2_ReadWriteByte(reg);//發送寄存器號 SPI2_ReadWriteByte(value); //寫入寄存器的值NRF24L01_CSN=1; //禁止SPI傳輸 return(status); //返回狀態值 } //讀取SPI寄存器值 //reg:要讀的寄存器 u8 NRF24L01_Read_Reg(u8 reg) {u8 reg_val; NRF24L01_CSN = 0; //使能SPI傳輸 SPI2_ReadWriteByte(reg); //發送寄存器號reg_val=SPI2_ReadWriteByte(0XFF);//讀取寄存器內容NRF24L01_CSN = 1; //禁止SPI傳輸 return(reg_val); //返回狀態值 } //在指定位置讀出指定長度的數據 //reg:寄存器(位置) //*pBuf:數據指針 //len:數據長度 //返回值,此次讀到的狀態寄存器值 u8 NRF24L01_Read_Buf(u8 reg,u8 *pBuf,u8 len) {u8 status,u8_ctr; NRF24L01_CSN = 0; //使能SPI傳輸status=SPI2_ReadWriteByte(reg);//發送寄存器值(位置),并讀取狀態值 for(u8_ctr=0;u8_ctr<len;u8_ctr++)pBuf[u8_ctr]=SPI2_ReadWriteByte(0XFF);//讀出數據NRF24L01_CSN=1; //關閉SPI傳輸return status; //返回讀到的狀態值 } //在指定位置寫指定長度的數據 //reg:寄存器(位置) //*pBuf:數據指針 //len:數據長度 //返回值,此次讀到的狀態寄存器值 u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 len) {u8 status,u8_ctr; NRF24L01_CSN = 0; //使能SPI傳輸status = SPI2_ReadWriteByte(reg);//發送寄存器值(位置),并讀取狀態值for(u8_ctr=0; u8_ctr<len; u8_ctr++)SPI2_ReadWriteByte(*pBuf++); //寫入數據 NRF24L01_CSN = 1; //關閉SPI傳輸return status; //返回讀到的狀態值 } //啟動NRF24L01發送一次數據 //txbuf:待發送數據首地址 //返回值:發送完成狀況 u8 NRF24L01_TxPacket(u8 *txbuf) {u8 sta;SPI2_SetSpeed(SPI_BaudRatePrescaler_8);//spi速度為9Mhz(24L01的最大SPI時鐘為10Mhz) NRF24L01_CE=0;NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);//寫數據到TX BUF 32個字節NRF24L01_CE=1;//啟動發送 while(NRF24L01_IRQ!=0);//等待發送完成sta=NRF24L01_Read_Reg(STATUS); //讀取狀態寄存器的值 NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中斷標志if(sta&MAX_TX)//達到最大重發次數{NRF24L01_Write_Reg(FLUSH_TX,0xff);//清除TX FIFO寄存器 return MAX_TX; }if(sta&TX_OK)//發送完成{return TX_OK;}return 0xff;//其他原因發送失敗 } //啟動NRF24L01發送一次數據 //txbuf:待發送數據首地址 //返回值:0,接收完成;其他,錯誤代碼 u8 NRF24L01_RxPacket(u8 *rxbuf) {u8 sta; SPI2_SetSpeed(SPI_BaudRatePrescaler_8); //spi速度為9Mhz(24L01的最大SPI時鐘為10Mhz) sta=NRF24L01_Read_Reg(STATUS); //讀取狀態寄存器的值 NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中斷標志if(sta&RX_OK)//接收到數據{NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//讀取數據NRF24L01_Write_Reg(FLUSH_RX,0xff);//清除RX FIFO寄存器 return 0; } return 1;//沒收到任何數據 } //該函數初始化NRF24L01到RX模式 //設置RX地址,寫RX數據寬度,選擇RF頻道,波特率和LNA HCURR //當CE變高后,即進入RX模式,并可以接收數據了 void NRF24L01_RX_Mode(void) {NRF24L01_CE=0; NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH);//寫RX節點地址NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01); //使能通道0的自動應答 NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01);//使能通道0的接收地址 NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40); //設置RF通信頻率 NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//選擇通道0的有效數據寬度 NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);//設置TX發射參數,0db增益,2Mbps,低噪聲增益開啟 NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG, 0x0f);//配置基本工作模式的參數;PWR_UP,EN_CRC,16BIT_CRC,接收模式 NRF24L01_CE = 1; //CE為高,進入接收模式 } //該函數初始化NRF24L01到TX模式 //設置TX地址,寫TX數據寬度,設置RX自動應答的地址,填充TX發送數據,選擇RF頻道,波特率和LNA HCURR //PWR_UP,CRC使能 //當CE變高后,即進入RX模式,并可以接收數據了 //CE為高大于10us,則啟動發送. void NRF24L01_TX_Mode(void) { NRF24L01_CE=0; NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS,TX_ADR_WIDTH);//寫TX節點地址 NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH); //設置TX節點地址,主要為了使能ACK NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01); //使能通道0的自動應答 NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址 NRF24L01_Write_Reg(NRF_WRITE_REG+SETUP_RETR,0x1a);//設置自動重發間隔時間:500us + 86us;最大自動重發次數:10次NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40); //設置RF通道為40NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f); //設置TX發射參數,0db增益,2Mbps,低噪聲增益開啟 NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0e); //配置基本工作模式的參數;PWR_UP,EN_CRC,16BIT_CRC,接收模式,開啟所有中斷NRF24L01_CE=1;//CE為高,10us后啟動發送 }

spi.c
main.c

#include "led.h" #include "delay.h" #include "key.h" #include "sys.h" #include "lcd.h" #include "usart.h" #include "24l01.h" /************************************************ALIENTEK戰艦STM32開發板實驗33無線通信 實驗技術支持:www.openedv.com淘寶店鋪:http://eboard.taobao.com 關注微信公眾平臺微信號:"正點原子",免費獲取STM32資料。廣州市星翼電子科技有限公司 作者:正點原子 @ALIENTEK ************************************************/int main(void){ u8 key,mode;u16 t=0; u8 tmp_buf[33]; delay_init(); //延時函數初始化 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//設置中斷優先級分組為組2:2位搶占優先級,2位響應優先級uart_init(115200); //串口初始化為115200LED_Init(); //初始化與LED連接的硬件接口KEY_Init(); //初始化按鍵LCD_Init(); //初始化LCD NRF24L01_Init(); //初始化NRF24L01 POINT_COLOR=RED; //設置字體為紅色 LCD_ShowString(30,50,200,16,16,"WarShip STM32"); LCD_ShowString(30,70,200,16,16,"NRF24L01 TEST"); LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");LCD_ShowString(30,110,200,16,16,"2015/1/17"); while(NRF24L01_Check()){LCD_ShowString(30,130,200,16,16,"NRF24L01 Error");delay_ms(200);LCD_Fill(30,130,239,130+16,WHITE);delay_ms(200);}LCD_ShowString(30,130,200,16,16,"NRF24L01 OK"); while(1){ key=KEY_Scan(0);if(key==KEY0_PRES){mode=0; break;}else if(key==KEY1_PRES){mode=1;break;}t++;if(t==100)LCD_ShowString(10,150,230,16,16,"KEY0:RX_Mode KEY1:TX_Mode"); //閃爍顯示提示信息if(t==200){ LCD_Fill(10,150,230,150+16,WHITE);t=0; }delay_ms(5); } LCD_Fill(10,150,240,166,WHITE);//清空上面的顯示 POINT_COLOR=BLUE;//設置字體為藍色 if(mode==0)//RX模式{LCD_ShowString(30,150,200,16,16,"NRF24L01 RX_Mode"); LCD_ShowString(30,170,200,16,16,"Received DATA:"); NRF24L01_RX_Mode(); while(1){ if(NRF24L01_RxPacket(tmp_buf)==0)//一旦接收到信息,則顯示出來.{tmp_buf[32]=0;//加入字符串結束符LCD_ShowString(0,190,lcddev.width-1,32,16,tmp_buf); }else delay_us(100); t++;if(t==10000)//大約1s鐘改變一次狀態{t=0;LED0=!LED0;} }; }else//TX模式{ LCD_ShowString(30,150,200,16,16,"NRF24L01 TX_Mode"); NRF24L01_TX_Mode();mode=' ';//從空格鍵開始 while(1){ if(NRF24L01_TxPacket(tmp_buf)==TX_OK){LCD_ShowString(30,170,239,32,16,"Sended DATA:"); LCD_ShowString(0,190,lcddev.width-1,32,16,tmp_buf); key=mode;for(t=0;t<32;t++){key++;if(key>('~'))key=' ';tmp_buf[t]=key; }mode++; if(mode>'~')mode=' '; tmp_buf[32]=0;//加入結束符 }else{ LCD_Fill(0,170,lcddev.width,170+16*3,WHITE);//清空顯示 LCD_ShowString(30,170,lcddev.width-1,32,16,"Send Failed "); };LED0=!LED0;delay_ms(1500); };} }

485通信實驗

485接口原理

FLASH模擬EEPROM

FLASH介紹


FLASH操作(讀、寫、擦除)






寄存器




常用庫函數





程序編寫

stmflash.h

#ifndef __STMFLASH_H__ #define __STMFLASH_H__ #include "sys.h" // //本程序只供學習使用,未經作者許可,不得用于其它任何用途 //ALIENTEK戰艦STM32開發板 //STM32 FLASH 驅動代碼 //正點原子@ALIENTEK //技術論壇:www.openedv.com //修改日期:2012/9/13 //版本:V1.0 //版權所有,盜版必究。 //Copyright(C) 廣州市星翼電子科技有限公司 2009-2019 //All rights reserved //// //用戶根據自己的需要設置 #define STM32_FLASH_SIZE 512 //所選STM32的FLASH容量大小(單位為K) #define STM32_FLASH_WREN 1 //使能FLASH寫入(0,不是能;1,使能) ////FLASH起始地址 #define STM32_FLASH_BASE 0x08000000 //STM32 FLASH的起始地址 //FLASH解鎖鍵值u16 STMFLASH_ReadHalfWord(u32 faddr); //讀出半字 void STMFLASH_WriteLenByte(u32 WriteAddr,u32 DataToWrite,u16 Len); //指定地址開始寫入指定長度的數據 u32 STMFLASH_ReadLenByte(u32 ReadAddr,u16 Len); //指定地址開始讀取指定長度數據 void STMFLASH_Write(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite); //從指定地址開始寫入指定長度的數據 void STMFLASH_Read(u32 ReadAddr,u16 *pBuffer,u16 NumToRead); //從指定地址開始讀出指定長度的數據//測試寫入 void Test_Write(u32 WriteAddr,u16 WriteData); #endif

stmflash.c

#include "stmflash.h" #include "delay.h" #include "usart.h"// //本程序只供學習使用,未經作者許可,不得用于其它任何用途 //ALIENTEK戰艦STM32開發板 //STM32 FLASH 驅動代碼 //正點原子@ALIENTEK //技術論壇:www.openedv.com //修改日期:2012/9/13 //版本:V1.0 //版權所有,盜版必究。 //Copyright(C) 廣州市星翼電子科技有限公司 2009-2019 //All rights reserved ////讀取指定地址的半字(16位數據) //faddr:讀地址(此地址必須為2的倍數!!) //返回值:對應數據. u16 STMFLASH_ReadHalfWord(u32 faddr) {return *(vu16*)faddr; } #if STM32_FLASH_WREN //如果使能了寫 //不檢查的寫入(寫之前要擦除,檢查是否擦除了,這里是已經檢查過了直接寫入) //WriteAddr:起始地址 //pBuffer:數據指針 //NumToWrite:半字(16位)數 void STMFLASH_Write_NoCheck(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite) { u16 i;for(i=0;i<NumToWrite;i++){FLASH_ProgramHalfWord(WriteAddr,pBuffer[i]);WriteAddr+=2;//地址增加2.} } //從指定地址開始寫入指定長度的數據 //WriteAddr:起始地址(此地址必須為2的倍數!!) //pBuffer:數據指針 //NumToWrite:半字(16位)數(就是要寫入的16位(半字)數據的個數.) #if STM32_FLASH_SIZE<256 #define STM_SECTOR_SIZE 1024 //字節 #else #define STM_SECTOR_SIZE 2048 #endif u16 STMFLASH_BUF[STM_SECTOR_SIZE/2];//最多是2K字節 void STMFLASH_Write(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite) {u32 secpos; //扇區地址u16 secoff; //扇區內偏移地址(16位字計算)u16 secremain; //扇區內剩余地址(16位字計算) u16 i; u32 offaddr; //去掉0X08000000后的地址 基地址 flash的size(宏定義512)if(WriteAddr<STM32_FLASH_BASE||(WriteAddr>=(STM32_FLASH_BASE+1024*STM32_FLASH_SIZE)))return;//非法地址,地址越界FLASH_Unlock(); //解鎖offaddr=WriteAddr-STM32_FLASH_BASE; //實際偏移地址.secpos=offaddr/STM_SECTOR_SIZE; //扇區地址(落在第幾頁sector) 0~127 for STM32F103RBT6secoff=(offaddr%STM_SECTOR_SIZE)/2; //在扇區內的偏移(2個字節為基本單位.)secremain=STM_SECTOR_SIZE/2-secoff; //扇區剩余空間大小 if(NumToWrite<=secremain)secremain=NumToWrite;//不大于該扇區范圍while(1) { //讀到buf數組里面 STMFLASH_Read(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);//讀出整個扇區的內容for(i=0;i<secremain;i++)//校驗數據{if(STMFLASH_BUF[secoff+i]!=0XFFFF)break;//需要擦除 擦除成功都是FF }if(i<secremain)//需要擦除{FLASH_ErasePage(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE);//擦除這個扇區for(i=0;i<secremain;i++)//復制到flash里面{STMFLASH_BUF[i+secoff]=pBuffer[i]; }STMFLASH_Write_NoCheck(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);//寫入整個扇區 }else STMFLASH_Write_NoCheck(WriteAddr,pBuffer,secremain);//寫已經擦除了的,直接寫入扇區剩余區間. if(NumToWrite==secremain)break;//寫入結束了 就是沒跨越頁else//寫入未結束 跨頁了{secpos++; //扇區地址增1secoff=0; //偏移位置為0 pBuffer+=secremain; //指針偏移WriteAddr+=(secremain*2); //寫地址偏移 NumToWrite-=secremain; //字節(16位)數遞減if(NumToWrite>(STM_SECTOR_SIZE/2))secremain=STM_SECTOR_SIZE/2;//下一個扇區還是寫不完else secremain=NumToWrite;//下一個扇區可以寫完了} }; FLASH_Lock();//上鎖 } #endif//從指定地址開始讀出指定長度的數據 //ReadAddr:起始地址 //pBuffer:數據指針 //NumToWrite:半字(16位)數 void STMFLASH_Read(u32 ReadAddr,u16 *pBuffer,u16 NumToRead) {u16 i;for(i=0;i<NumToRead;i++){pBuffer[i]=STMFLASH_ReadHalfWord(ReadAddr);//讀取2個字節(半字)ReadAddr+=2;//偏移2個字節. } }// //WriteAddr:起始地址 //WriteData:要寫入的數據 void Test_Write(u32 WriteAddr,u16 WriteData) {STMFLASH_Write(WriteAddr,&WriteData,1);//寫入一個字 }

main.c

#include "led.h" #include "delay.h" #include "key.h" #include "sys.h" #include "lcd.h" #include "usart.h" #include "stmflash.h"/************************************************ALIENTEK戰艦STM32開發板實驗34FLASH模擬EEPROM 實驗 技術支持:www.openedv.com淘寶店鋪:http://eboard.taobao.com 關注微信公眾平臺微信號:"正點原子",免費獲取STM32資料。廣州市星翼電子科技有限公司 作者:正點原子 @ALIENTEK ************************************************///要寫入到STM32 FLASH的字符串數組 const u8 TEXT_Buffer[]={"STM32F103 FLASH TEST"}; #define SIZE sizeof(TEXT_Buffer) //數組長度 #define FLASH_SAVE_ADDR 0X08070000 //設置FLASH 保存地址(必須為偶數,且其值要大于本代碼所占用FLASH的大小+0X08000000)int main(void){ u8 key;u16 i=0;u8 datatemp[SIZE];delay_init(); //延時函數初始化 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//設置中斷優先級分組為組2:2位搶占優先級,2位響應優先級uart_init(115200); //串口初始化為115200LED_Init(); //初始化與LED連接的硬件接口KEY_Init(); //初始化按鍵LCD_Init(); //初始化LCD POINT_COLOR=RED; //設置字體為紅色 LCD_ShowString(30,50,200,16,16,"WarShip STM32"); LCD_ShowString(30,70,200,16,16,"FLASH EEPROM TEST"); LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");LCD_ShowString(30,110,200,16,16,"2015/1/18"); LCD_ShowString(30,130,200,16,16,"KEY1:Write KEY0:Read");while(1){key=KEY_Scan(0);if(key==KEY1_PRES) //KEY1按下,寫入STM32 FLASH{LCD_Fill(0,170,239,319,WHITE);//清除半屏 LCD_ShowString(30,170,200,16,16,"Start Write FLASH....");STMFLASH_Write(FLASH_SAVE_ADDR,(u16*)TEXT_Buffer,SIZE);LCD_ShowString(30,170,200,16,16,"FLASH Write Finished!");//提示傳送完成}if(key==KEY0_PRES) //KEY0按下,讀取字符串并顯示{LCD_ShowString(30,170,200,16,16,"Start Read FLASH.... ");STMFLASH_Read(FLASH_SAVE_ADDR,(u16*)datatemp,SIZE);LCD_ShowString(30,170,200,16,16,"The Data Readed Is: ");//提示傳送完成LCD_ShowString(30,190,200,16,16,datatemp);//顯示讀到的字符串}i++;delay_ms(10); if(i==20){LED0=!LED0;//提示系統正在運行 i=0;} } }

串口IAP實驗(在程序中編程In Application Programming)

STM32IAP介紹




IAP運作流程







IAP配置

bootloader的三個作用(程序要實現的功能):

1、接收APP的bin文件
2、將這個文件寫到flash的某個區域
3、實現跳轉

實驗程序

usart.h

#ifndef __USART_H #define __USART_H #include "stdio.h" #include "sys.h" #define USART_REC_LEN 55*1024 //定義最大接收字節數 55K字節,bin文件不能大于55k 實際應用中根據工程需要修改 #define EN_USART1_RX 1 //使能(1)/禁止(0)串口1接收extern u8 USART_RX_BUF[USART_REC_LEN]; //接收緩沖,最大USART_REC_LEN個字節.末字節為換行符 extern u16 USART_RX_STA; //接收狀態標記 extern u16 USART_RX_CNT; //接收的字節數 //如果想串口中斷接收,請不要注釋以下宏定義 void uart_init(u32 bound); #endif

usart.c

#include "sys.h" #include "usart.h" // //如果使用ucos,則包括下面的頭文件即可. #if SYSTEM_SUPPORT_OS #include "includes.h" //ucos 使用 #endif// //加入以下代碼,支持printf函數,而不需要選擇use MicroLIB #if 1 #pragma import(__use_no_semihosting) //標準庫需要的支持函數 struct __FILE { int handle; }; FILE __stdout; //定義_sys_exit()以避免使用半主機模式 void _sys_exit(int x) { x = x; } //重定義fputc函數 int fputc(int ch, FILE *f) { while((USART1->SR&0X40)==0);//循環發送,直到發送完畢 USART1->DR = (u8) ch; return ch; } #endif /*使用microLib的方法*//* int fputc(int ch, FILE *f) {USART_SendData(USART1, (uint8_t) ch);while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {} return ch; } int GetKey (void) { while (!(USART1->SR & USART_FLAG_RXNE));return ((int)(USART1->DR & 0x1FF)); } */#if EN_USART1_RX //如果使能了接收 //串口1中斷服務程序 //注意,讀取USARTx->SR能避免莫名其妙的錯誤 u8 USART_RX_BUF[USART_REC_LEN] __attribute__ ((at(0X20001000)));//接收緩沖,最大USART_REC_LEN個字節,并限定數組存放在SRAM區域的起始地址為0X20001000(前面留出一定空間給bootloader使用) //接收狀態 //bit15, 接收完成標志 //bit14, 接收到0x0d //bit13~0, 接收到的有效字節數目 u16 USART_RX_STA=0; //接收狀態標記 u16 USART_RX_CNT=0; //接收的字節數 void uart_init(u32 bound) {//GPIO端口設置GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA時鐘//USART1_TX GPIOA.9GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復用推挽輸出GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9//USART1_RX GPIOA.10初始化GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空輸入GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10 //Usart1 NVIC 配置NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//搶占優先級3NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子優先級3NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能NVIC_Init(&NVIC_InitStructure); //根據指定的參數初始化VIC寄存器//USART 初始化設置USART_InitStructure.USART_BaudRate = bound;//串口波特率USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字長為8位數據格式USART_InitStructure.USART_StopBits = USART_StopBits_1;//一個停止位USART_InitStructure.USART_Parity = USART_Parity_No;//無奇偶校驗位USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//無硬件數據流控制USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收發模式USART_Init(USART1, &USART_InitStructure); //初始化串口1USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//開啟串口接受中斷USART_Cmd(USART1, ENABLE); //使能串口1 }void USART1_IRQHandler(void)//每接收一個字節都要執行中斷服務函數 {u8 res; #ifdef OS_CRITICAL_METHOD //如果OS_CRITICAL_METHOD定義了,說明使用ucosII了.OSIntEnter(); #endifif(USART1->SR&(1<<5))//接收到數據{ res=USART1->DR; if(USART_RX_CNT<USART_REC_LEN){USART_RX_BUF[USART_RX_CNT]=res;//接收到的數據存放在buf里,后續寫入指定flash區域USART_RX_CNT++; }} #ifdef OS_CRITICAL_METHOD //如果OS_CRITICAL_METHOD定義了,說明使用ucosII了.OSIntExit(); #endif } #endif

iap.h

#ifndef __IAP_H__ #define __IAP_H__ #include "sys.h" typedef void (*iapfun)(void); //定義一個函數類型的參數.#define FLASH_APP1_ADDR 0x08010000 //第一個應用程序起始地址(存放在FLASH)//保留0X08000000~0X0800FFFF的空間(64K 根據實際大小來)為IAP使用void iap_load_app(u32 appxaddr); //執行flash里面的app程序,起始地址為appxaddr void iap_load_appsram(u32 appxaddr); //執行SRAM里面的app程序 void iap_write_appbin(u32 appxaddr,u8 *appbuf,u32 applen); //在flash指定地址appxaddr開始,寫入bin #endif

iap.c

#include "sys.h" #include "delay.h" #include "usart.h" #include "stmflash.h"//要對flash進行操作,引入頭文件 #include "iap.h"iapfun jump2app; u16 iapbuf[1024]; //appxaddr:應用程序的起始地址 //appbuf:應用程序CODE. //appsize:應用程序大小(字節). void iap_write_appbin(u32 appxaddr,u8 *appbuf,u32 appsize) {u16 t;u16 i=0;u16 temp;u32 fwaddr=appxaddr;//當前寫入的地址u8 *dfu=appbuf;for(t=0;t<appsize;t+=2){ temp=(u16)dfu[1]<<8;temp+=(u16)dfu[0]; dfu+=2;//偏移2個字節iapbuf[i++]=temp; if(i==1024){i=0;STMFLASH_Write(fwaddr,iapbuf,1024); fwaddr+=2048;//偏移2048 16=2*8.所以要乘以2.}}if(i)STMFLASH_Write(fwaddr,iapbuf,i);//將最后的一些內容字節寫進去. }//跳轉到應用程序段 //appxaddr:用戶代碼起始地址. void iap_load_app(u32 appxaddr) {if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000) //檢查棧頂地址是否合法.{ jump2app=(iapfun)*(vu32*)(appxaddr+4); //用戶代碼區第二個字為程序開始地址(復位地址) MSR_MSP(*(vu32*)appxaddr); //初始化APP堆棧指針(用戶代碼區的第一個字用于存放棧頂地址)jump2app(); //跳轉到APP.} }

main.c

#include "led.h" #include "delay.h" #include "key.h" #include "sys.h" #include "lcd.h" #include "usart.h" #include "stmflash.h" #include "iap.h"int main(void) { u8 t;u8 key;u16 oldcount=0; //老的串口接收數據值u16 applenth=0; //接收到的app代碼長度u8 clearflag=0; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //設置NVIC中斷分組2:2位搶占優先級,2位響應優先級uart_init(115200); //串口初始化為115200delay_init(); //延時初始化 LED_Init(); //初始化與LED連接的硬件接口KEY_Init(); //初始化按鍵LCD_Init(); //初始化LCD POINT_COLOR=RED;//設置字體為紅色 LCD_ShowString(30,50,200,16,16,"Warship STM32"); LCD_ShowString(30,70,200,16,16,"IAP TEST"); LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");LCD_ShowString(30,110,200,16,16,"2015/1/27"); LCD_ShowString(30,130,200,16,16,"KEY_UP:Copy APP2FLASH");LCD_ShowString(30,150,200,16,16,"KEY2:Erase SRAM APP");LCD_ShowString(30,170,200,16,16,"KEY1:Run FLASH APP");LCD_ShowString(30,190,200,16,16,"KEY0:Run SRAM APP");POINT_COLOR=BLUE;//顯示提示信息POINT_COLOR=BLUE;//設置字體為藍色 while(1){if(USART_RX_CNT){if(oldcount==USART_RX_CNT)//新周期內,沒有收到任何數據,認為本次數據接收完成.{applenth=USART_RX_CNT;oldcount=0;USART_RX_CNT=0;printf("用戶程序接收完成!\r\n");//程序接收完成printf("代碼長度:%dBytes\r\n",applenth);}else oldcount=USART_RX_CNT; }t++;delay_ms(10);if(t==30){LED0=!LED0;t=0;if(clearflag){clearflag--;if(clearflag==0)LCD_Fill(30,210,240,210+16,WHITE);//清除顯示}} key=KEY_Scan(0); //按鍵掃描if(key==WKUP_PRES)//按鍵按下{if(applenth){printf("開始更新固件...\r\n"); LCD_ShowString(30,210,200,16,16,"Copying APP2FLASH...");if(((*(vu32*)(0X20001000+4))&0xFF000000)==0x08000000)//判斷是否為0X08XXXXXX.{ iap_write_appbin(FLASH_APP1_ADDR,USART_RX_BUF,applenth);//將bin程序寫入到FLASH LCD_ShowString(30,210,200,16,16,"Copy APP Successed!!");printf("固件更新完成!\r\n"); }else {LCD_ShowString(30,210,200,16,16,"Illegal FLASH APP! "); printf("非FLASH應用程序!\r\n");}}else {printf("沒有可以更新的固件!\r\n");LCD_ShowString(30,210,200,16,16,"No APP!");}clearflag=7;//標志更新了顯示,并且設置7*300ms后清除顯示 }if(key==KEY2_PRES)//按鍵2按下{if(applenth){ printf("固件清除完成!\r\n"); LCD_ShowString(30,210,200,16,16,"APP Erase Successed!");applenth=0;//置0清除固件}else {printf("沒有可以清除的固件!\r\n");LCD_ShowString(30,210,200,16,16,"No APP!");}clearflag=7;//標志更新了顯示,并且設置7*300ms后清除顯示 }if(key==KEY1_PRES)//按鍵1按下{printf("開始執行FLASH用戶代碼!!\r\n");if(((*(vu32*)(FLASH_APP1_ADDR+4))&0xFF000000)==0x08000000)//判斷是否為0X08XXXXXX.{ iap_load_app(FLASH_APP1_ADDR);//跳轉執行FLASH APP代碼}else {printf("非FLASH應用程序,無法執行!\r\n");LCD_ShowString(30,210,200,16,16,"Illegal FLASH APP!"); } clearflag=7;//標志更新了顯示,并且設置7*300ms后清除顯示 }if(key==KEY0_PRES)//按鍵0按下{printf("開始執行SRAM用戶代碼!!\r\n");if(((*(vu32*)(0X20001000+4))&0xFF000000)==0x20000000)//判斷是否為0X20XXXXXX.{ iap_load_app(0X20001000);//執行SRAM地址程序}else {printf("非SRAM應用程序,無法執行!\r\n");LCD_ShowString(30,210,200,16,16,"Illegal SRAM APP!"); } clearflag=7;//標志更新了顯示,并且設置7*300ms后清除顯示 } } }

APP 程序起始地址設置方法

詳細參照開發手冊。

中斷向量表的偏移量設置方法

藍牙模塊HC05使用

模塊介紹






模塊AT指令集


與上位機串口通信

與手機藍牙調試助手通信


藍牙模塊接收到手機端發來的數據,通過串口發送出去,在上位機使用串口調試助手可以查看到。

與單片機連接通信



總結

以上是生活随笔為你收集整理的正点原子STM32的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。