stm32外設(shè)指的是單片機(jī)外部的外圍功能模塊,比如鍵盤(pán)控制芯片,液晶,A/D轉(zhuǎn)換芯片,等等。外設(shè)可通過(guò)單片機(jī)的I/O,SPI,I2C等總線控制。
常見(jiàn)stm32外設(shè):基本IO、定時(shí)器TIM、串口USART、ADC模數(shù)轉(zhuǎn)換、DAC數(shù)模轉(zhuǎn)換、SPI串行通信、EXIT外部中斷、BKP備份數(shù)據(jù)、RTC鬧鐘SysTick系統(tǒng)滴答、WDG看門狗(獨(dú)立+窗口)、DMA傳輸數(shù)據(jù)、片內(nèi)FLASH編程、FSMC讀寫(xiě)外部SRAM、外部NorFlash操作等。
stm32外設(shè)的初始化和設(shè)置:
在設(shè)置一個(gè)外設(shè)前,必須調(diào)用以下一個(gè)函數(shù)來(lái)使能它的時(shí)鐘
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_PPPx,ENABLE);
1,在主應(yīng)用文件中聲明一個(gè)結(jié)構(gòu)PPP_InitTypeDef,例如:PPP_InitTypeDef
PPP_InitStructure;
2,為變量PPP_InitStructure的各個(gè)結(jié)構(gòu)成員填入允許的值??梢圆捎靡韵?種方式:
a)PPP_InitStructure.member1=val1;
b)PPP_StructInit(&PPP_InitStructure)PP_InitStructure.memberX=valX;
3,調(diào)用函數(shù)PPP_Init()來(lái)初始化外設(shè)PPP;
4,在這一步,外設(shè)PPP已被初始化??梢哉{(diào)用函數(shù)PPP_Cmd()來(lái)使能之。
使用STM32外設(shè)的步驟
1,PPP_Init()函數(shù),其功能是根據(jù)PPP_InitTypeDef中指定的參數(shù),初始化外設(shè)PPP,如TIM_Init()名為PPP_DeInit()函數(shù),其功能為復(fù)位外設(shè)PPP的所有寄存器至缺省值。
2,PPP_StructInit()函數(shù),其功能為通過(guò)設(shè)置PPP_InitTypeDef結(jié)構(gòu)中的各種參數(shù)來(lái)定義外設(shè)的功能,例如:USART_StructInit()
3,PPP_Cmd()函數(shù),其功能為使能或者失能外設(shè)PPP,例如:SPI_Cmd
4,PPP_ITConfig()函數(shù),其功能為使能或者失能來(lái)自外設(shè)PPP的中斷源,例如:RCC_ITConfig
5,PPP_DMAConfig()的函數(shù),其功能為使能或者失能外PPP的DMA接口
6,PPP_GetFlagStatus()的函數(shù),其功能為檢查外設(shè)PPP某標(biāo)志位被設(shè)置與否
7,PPP_ClearFlag()的函數(shù),其功能為清除外設(shè)PPP標(biāo)志位,例如:I2C_ClearFlag.
8,PPP_GetITStatus()的函數(shù),其功能為判斷來(lái)自外設(shè)PPP的中斷發(fā)生與否
?
9,PPP_ClearITPendingBit()的函數(shù),其功能為清除外設(shè)PPP中斷待處理標(biāo)志位
STM32外設(shè)使用要點(diǎn)
1、時(shí)鐘安全系統(tǒng)(CSS)
時(shí)鐘安全系統(tǒng)被激活后,時(shí)鐘監(jiān)控器將實(shí)時(shí)監(jiān)控外部高速振蕩器;如果HSE時(shí)鐘發(fā)生故障,外部振蕩器自動(dòng)被關(guān)閉,產(chǎn)生時(shí)鐘安全中斷,該中斷被連接到Cortex-M3的NMI的中斷;同時(shí)CSS將內(nèi)部RC振蕩器切換為STM32的系統(tǒng)時(shí)鐘源(對(duì)于STM32F103,時(shí)鐘失效事件還將被送到高級(jí)定時(shí)器TIM1的剎車輸入端,用以實(shí)現(xiàn)電機(jī)保護(hù)控制)。
操作流程:
1)、啟動(dòng)時(shí)鐘安全系統(tǒng)CSS: RCC_ClockSecuritySystemCmd(ENABLE); (NMI中斷是不可屏蔽的!)
2)外部振蕩器失效時(shí),產(chǎn)生NMI中斷,對(duì)應(yīng)的中斷程序:
void NMIException(void)
{
if (RCC_GetITStatus(RCC_IT_CSS) ! RESET)
{ // HSE、PLL已被禁止(但是PLL設(shè)置未變)
…… // 客戶添加相應(yīng)的系統(tǒng)保護(hù)代碼處
// 下面為HSE恢復(fù)后的預(yù)設(shè)置代碼
RCC_HSEConfig(RCC_HSE_ON); // 使能HSE
RCC_ITConfig(RCC_IT_HSERDY, ENABLE); // 使能HSE就緒中斷
RCC_ITConfig(RCC_IT_PLLRDY, ENABLE); // 使能PLL就緒中斷
RCC_ClearITPendingBit(RCC_IT_CSS); // 清除時(shí)鐘安全系統(tǒng)中斷的掛起位
// 至此,一旦HSE時(shí)鐘恢復(fù),將發(fā)生HSERDY中斷,在RCC中斷處理程序里, 系統(tǒng)時(shí)鐘可以設(shè)置到以前的狀態(tài)
}
}
3)、在RCC的中斷處理程序中,再對(duì)HSE和PLL進(jìn)行相應(yīng)的處理。
注意:一旦CSS被激活,當(dāng)HSE時(shí)鐘出現(xiàn)故障時(shí)將產(chǎn)生CSS中斷,同時(shí)自動(dòng)產(chǎn)生 NMI。NMI將被不斷執(zhí)行,直到CSS中斷掛起位被清除。因此,在NMI的處理程序中 必須通過(guò)設(shè)置時(shí)鐘中斷寄存器(RCC_CIR)里的CSSC位來(lái)清除CSS中斷。
2、SysTick工作原理
Cortex-M3的內(nèi)核中包含一個(gè)SysTick時(shí)鐘。SysTick 為一個(gè)24位遞減計(jì)數(shù)器,SysTick設(shè)定初值并使能后, 每經(jīng)過(guò)1個(gè)系統(tǒng)時(shí)鐘周期,計(jì)數(shù)值就減1。計(jì)數(shù)到0時(shí), SysTick計(jì)數(shù)器自動(dòng)重裝初值并繼續(xù)計(jì)數(shù),同時(shí)內(nèi)部的 COUNTFLAG標(biāo)志會(huì)置位,觸發(fā)中斷(如果中斷使能)。
3、內(nèi)部時(shí)鐘輸出PA.8(MCO)
STM32的PA.8引腳具有復(fù)用功能——時(shí)鐘輸出(MCO), 該功能能將STM32內(nèi)部的時(shí)鐘通過(guò)PA.8輸出。
操作流程:
1)、設(shè)置PA.8為復(fù)用Push-Pull模式。
GPIO_InitStructure.GPIO_Pin GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
2)、選擇輸出時(shí)鐘源。
時(shí)鐘的選擇由時(shí)鐘配置寄存器(RCC_CFGR)中的MCO[2:0]位控制。
RCC_MCOConfig(RCC_MCO);
參數(shù)RCC_MCO為要輸出的內(nèi)部時(shí)鐘:
RCC_MCO_NoClock --- 無(wú)時(shí)鐘輸出
RCC_MCO_SYSCLK --- 輸出系統(tǒng)時(shí)鐘(SysCLK)
RCC_MCO_HSI --- 輸出內(nèi)部高速8MHz的RC振蕩器的時(shí)鐘(HSI)
RCC_MCO_HSE --- 輸出高速外部時(shí)鐘信號(hào)(HSE)
RCC_MCO_PLLCLK_Div2 --- 輸出PLL倍頻后的二分頻時(shí)鐘(PLLCLK/2)
注:由于STM32 GPIO輸出管腳的最大響應(yīng)頻率為50MHz,如果輸出頻率超過(guò)50MHz,則輸出的波形會(huì)失真。
4、可編程電壓監(jiān)測(cè)器(PVD)
STM32內(nèi)部自帶PVD功能,用于對(duì)MCU供電電壓VDD進(jìn)行監(jiān)控。通過(guò)電源控制寄存器中的PLS[2:0]位可以用來(lái)設(shè)定監(jiān)控電壓的閥值,通過(guò)對(duì)外部電壓進(jìn)行比較來(lái)監(jiān)控電源。當(dāng)條件觸發(fā),需要系統(tǒng)進(jìn)入特別保護(hù)狀態(tài),執(zhí)行緊急關(guān)閉任務(wù):對(duì)系統(tǒng)的一些數(shù)據(jù)保存起來(lái),同時(shí)對(duì)外設(shè)進(jìn)行相應(yīng)的保護(hù)操作。
操作流程:
1)、系統(tǒng)啟動(dòng)后啟動(dòng)PVD,并開(kāi)啟相應(yīng)的中斷。
PWR_PVDLevelConfig(PWR_PVDLevel_2V8); // 設(shè)定監(jiān)控閥值
PWR_PVDCmd(ENABLE); // 使能PVD
EXTI_StructInit(&EXTI_InitStructure);
EXTI_InitStructure.EXTI_Line EXTI_Line16; // PVD連接到中斷線16上
EXTI_InitStructure.EXTI_Mode EXTI_Mode_Interrupt; //使用中斷模式
EXTI_InitStructure.EXTI_Trigger EXTI_Trigger_Raising;//電壓低于閥值時(shí)產(chǎn)生中斷
EXTI_InitStructure.EXTI_LineCmd ENABLE; // 使能中斷線
EXTI_Init(&EXTI_InitStructure); // 初始
EXTI_InitStructure.EXTI_Trigger的賦值可選項(xiàng):
EXTI_Trigger_Rising---表示電壓從高下降到低于設(shè)定閥值時(shí)產(chǎn)生中斷;
EXTI_Trigger_Falling---表示電壓從低上升到高于設(shè)定閥值時(shí)產(chǎn)生中斷;
EXTI_Trigger_Rising_Falling---表示電壓上升或下降越過(guò)設(shè)定閥值時(shí)都產(chǎn)生中斷。
2)、當(dāng)工作電壓低于設(shè)定閥值時(shí),將產(chǎn)生PVD中斷,在中斷程序中進(jìn)行相應(yīng)的處理:
void PVD_IRQHandler(void)
{
EXTI_ClearITPendingBit(EXTI_Line16);
…… // 用戶添加緊急處理代碼處
}
5、STM32上不使用外部晶振,OSC_IN和OSC_OUT的接法
1)、對(duì)于100腳或144腳的產(chǎn)品,OSC_IN應(yīng)接地,OSC_OUT應(yīng)懸空。
2)、對(duì)于少于100腳的產(chǎn)品,有2種接法:
2.1)、OSC_IN和OSC_OUT分別通過(guò)10K電阻接地。
此方法可提高EMC性能。
2.2)、分別重映射OSC_IN和OSC_OUT至PD0和PD1,再配置PD0和PD1為推挽輸出并輸出‘0’。
此方法可以減小功耗并(相對(duì)上面2.1),并節(jié)省2個(gè)外部電阻。
Interrupt/Evens
1、NVIC的優(yōu)先級(jí)概念占先式優(yōu)先級(jí) (pre-emption priority):
高占先式優(yōu)先級(jí)的中斷事件會(huì)打斷當(dāng)前的主程序/中斷程序運(yùn)行— —搶斷式優(yōu)先響應(yīng),俗稱中斷嵌套。
副優(yōu)先級(jí)(subpriority):
在占先式優(yōu)先級(jí)相同的情況下,高副優(yōu)先級(jí)的中斷優(yōu)先被響應(yīng);
在占先式優(yōu)先級(jí)相同的情況下,如果有低副優(yōu)先級(jí)中斷正在執(zhí)行, 高副優(yōu)先級(jí)的中斷要等待已被響應(yīng)的低副優(yōu)先級(jí)中斷執(zhí)行結(jié)束后才 能得到響應(yīng)——非搶斷式響應(yīng)(不能嵌套)。
2、判斷中斷是否會(huì)被響應(yīng)的依據(jù)
首先是占先式優(yōu)先級(jí),其次是副優(yōu)先級(jí);
占先式優(yōu)先級(jí)決定是否會(huì)有中斷嵌套;
Reset、NMI、Hard Fault 優(yōu)先級(jí)為負(fù)(高于普通中斷優(yōu)先級(jí))且不可調(diào)整。
3、STM32中用到的Cortex-M3寄存器說(shuō)明
在STM32中用到了Cortex-M3定義的三組寄存器,有關(guān)這三組寄存器的說(shuō)明不在STM32的技術(shù)手冊(cè)中,需要參考ARM公司發(fā)布的Cortex-M3 Technical Reference Manual (r2p0)。
在STM32的固件庫(kù)中定義了三個(gè)結(jié)構(gòu)體與這三個(gè)寄存器組相對(duì)應(yīng),這三個(gè)結(jié)構(gòu)體與ARM手冊(cè)中寄存器的對(duì)應(yīng)關(guān)系如下:
1)、NVIC寄存器組
STM32的固件庫(kù)中有如下定義:
typedef struct
{
vu32 ISER[2];
u32 RESERVED0[30];
vu32 ICER[2];
u32 RSERVED1[30];
vu32 ISPR[2];
u32 RESERVED2[30];
vu32 ICPR[2];
u32 RESERVED3[30];
vu32 IABR[2];
u32 RESERVED4[62];
vu32 IPR[11];
} NVIC_TypeDef;
它們對(duì)應(yīng)ARM手冊(cè)中的名稱為
ISER Interrupt Set-Enable Registers
ICER Interrupt Clear-Enable Registers
ISPR Interrupt Set-Pending Register
ICPR Interrupt Clear-Pending Register
IABR Active Bit Register
IPR Interrupt Priority Registers
每個(gè)寄存器有240位,以Interrupt Set-Enable Registers說(shuō)明,ISER[0]對(duì)應(yīng)中斷源0~31,ISER[1]對(duì)應(yīng)中斷源32~63,STM32只有60個(gè)中斷源,所以沒(méi)有ISER[2:7]。
參考STM32技術(shù)參考手冊(cè)中的中斷向量表,中斷源的位置為:
位置0 - WWDG Window Watchdog interrupt
位置1 - PVD PVD through EXTI Line detection interrupt
位置2 - TAMPER Tamper interrupt
位置58 - DMA2_Channel3 DMA2 Channel3 global interrupt
位置59 - DMA2_Channel4_5 DMA2 Channel4 and DMA2 Channel5 global interrupts
2)、系統(tǒng)控制寄存器組
STM32的固件庫(kù)中有如下定義:
typedef struct
{
vuc32 CPUID;
vu32 ICSR;
vu32 VTOR;
vu32 AIRCR;
vu32 SCR;
vu32 CCR;
vu32 SHPR[3];
vu32 SHCSR;
vu32 CFSR;
vu32 HFSR;
vu32 DFSR;
vu32 MMFAR;
vu32 BFAR;
vu32 AFSR;
} SCB_TypeDef; /* System Control Block Structure */
它們對(duì)應(yīng)ARM手冊(cè)中的名稱為
CPUID CPUID Base Register
ICSR Interrupt Control State Register
VTOR Vector Table Offset Register
AIRCR Application Interrupt/Reset Control Register
SCR System Control Register
CCR Configuration Control Register
SHPR System Handlers Priority Register
SHCSR System Handler Control and State Register
CFSR Configurable Fault Status Registers
HFSR Hard Fault Status Register
DFSR Debug Fault Status Register
MMFAR Mem Manage Address Register
BFAR Bus Fault Address Register
AFSR Auxiliary Fault Status Register
3)、系統(tǒng)時(shí)鐘寄存器組
STM32的固件庫(kù)中有如下定義:
typedef struct
{
vu32 CTRL;
vu32 LOAD;
vu32 VAL;
vuc32 CALIB;
} SysTick_TypeDef;
它們對(duì)應(yīng)ARM手冊(cè)中的名稱為
CTRL SysTick Control and Status Register
LOAD SysTick Reload Value Register
VAL SysTick Current Value Register
CALIB SysTick Calibration Value Register
DMA
1、DMA普通模式和循環(huán)模式的區(qū)別
循環(huán)模式:用于處理一個(gè)環(huán)形的緩沖區(qū),每輪傳輸結(jié)束時(shí)數(shù)據(jù)傳輸 的配置會(huì)自動(dòng)地更新為初始狀態(tài),DMA傳輸會(huì)連續(xù)不斷地進(jìn)行。
普通模式:在DMA傳輸結(jié)束時(shí),DMA通道被自動(dòng)關(guān)閉,進(jìn)一步的 DMA請(qǐng)求將不被滿足。
2、DMA傳輸需要指定的條件:
傳輸源:DMA控制器從傳輸源讀出數(shù)據(jù);
傳輸目標(biāo):DMA控制器將數(shù)據(jù)傳輸?shù)哪繕?biāo);
觸發(fā)信號(hào):用于觸發(fā)一次數(shù)據(jù)傳輸?shù)膭?dòng)作,執(zhí)行一個(gè)單位的傳輸源至傳輸目標(biāo)的數(shù)據(jù)傳輸??梢杂脕?lái)控制傳輸?shù)膯?dòng)條件。
ADC
1、STM32的內(nèi)部溫度傳感器
STM32內(nèi)部溫度傳感器與ADC的通道16相連,與ADC配 合使用實(shí)現(xiàn)溫度測(cè)量。測(cè)量范圍–40~125℃,精度 ± 1.5℃
操作流程:
1)、設(shè)置ADC相關(guān)參數(shù)
// ADC1 configuration -----------------------------
ADC_InitStructure.ADC_Mode ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode ENABLE;
ADC_InitStructure.ADC_ContinuousConvMode ENABLE;
ADC_InitStructure.ADC_ExternalTrigConv ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel 1;
ADC_Init(ADC1, &ADC_InitStructure);
2)、選中ADC1的通道16作為輸入,設(shè)置采樣時(shí)間17.1us ( Ncycle × tADC 17.1靤 )。
// ADC1 regular channel16 Temp Sensor configuration
ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 1, ADC_SampleTime_55Cycles5);
3)、設(shè)置寄存器ADC_CR2中的TSVREFE位激活溫度傳感器
// Enable the temperature sensor and vref internal channel
ADC_TempSensorVrefintCmd(ENABLE);
4)、轉(zhuǎn)換采樣值為溫度
ADC轉(zhuǎn)換結(jié)束以后,讀取ADC_DR寄存器中的結(jié)果,轉(zhuǎn)換溫度值計(jì)算公式如下:
V25 - VSENSE
T(℃) ------------ + 25
Avg_Slope
V25: 溫度傳感器在25℃時(shí) 的輸出電壓,典型值1.43 V。
VSENSE:溫度傳感器的當(dāng)前輸出電壓,與ADC_DR 寄存器中的結(jié)果ADC_ConvertedValue之間的轉(zhuǎn)換關(guān)系為:
ADC_ConvertedValue * Vdd
VSENSE --------------------------
Vdd_convert_value(0xFFF)
Avg_Slope:溫度傳感器輸出電壓和溫度的關(guān)聯(lián)參數(shù),典型值4.3 mV/℃。
//Converted Temperature
Vtemp_sensor ADC_ConvertedValue * Vdd / Vdd_convert_value;
Current_Temp (V25 - Vtemp_sensor)/Avg_Slope + 25;
2、VDDA的電壓范圍
STM32的數(shù)據(jù)手冊(cè)規(guī)定,VDD與VDDA之間的壓差不能大于300mV。ADC的工作電壓范圍在2.4V~3.6V,供電電壓VDD范圍在2.0V~3.6V.
1、STM32的USB中斷說(shuō)明
STM32的USB模塊可產(chǎn)生三種中斷:USB喚醒中斷、USB高優(yōu)先級(jí)中斷和USB低優(yōu)先級(jí)中斷,這三種中斷對(duì)應(yīng)事件如下:
1)、USB喚醒中斷 - 在中斷向量表中的位置是42
這個(gè)中斷在USB設(shè)備從暫停模式喚醒時(shí)產(chǎn)生,喚醒事件由USB_ISTR寄存器的WKUP位標(biāo)識(shí)。
2)、USB高優(yōu)先級(jí)中斷 - 在中斷向量表中的位置是19
這個(gè)中斷僅由USB同步(Isochronous)模式傳輸或雙緩沖塊(Bulk)傳輸模式下的正確傳輸事件產(chǎn)生,正確傳輸事件由USB_ISTR寄存器的CTR位標(biāo)識(shí)。
3)、USB低優(yōu)先級(jí)中斷 - 在中斷向量表中的位置是20
這個(gè)中斷由所有其它的USB事件產(chǎn)生,例如正確傳輸(不包括同步模式和雙緩沖塊模式)、USB復(fù)位等,事件標(biāo)志位在USB_ISTR寄存器中。
在STM提供的STM32 USB 開(kāi)發(fā)包中的例程包含了上述三種中斷的處理方法。例如在USB Speaker例程中,CTR_HP函數(shù)處理USB高優(yōu)先級(jí)中斷;在所有例子中都有USB_Istr()函數(shù)處理USB低優(yōu)先級(jí)中斷。
bxCAN
1、CAN波特率的設(shè)定計(jì)數(shù)
Etherne
SPI
1、SPI外設(shè)的NSS引腳設(shè)置為通用IO口
由于SPI外設(shè)的SPI_CR1寄存器中SSM置1時(shí),NSS引腳可被被釋放用于GPIO使用,因此無(wú)論是在SPI的主模式或是從模式下均可以將NSS引腳釋放,由軟件或硬件進(jìn)行NSS管理;
操作流程:
1)、初始化SPI外設(shè),設(shè)置NSS由軟件管理:
SPI_InitStructure.SPI_NSS SPI_NSS_Soft;
2)、如果NSS引腳用于其他外設(shè)時(shí),需要使能NSS輸出:
SPI_SSOutputCmd(SPIx, ENABLE);
2、SPI 單線傳輸
此模式下限制:只能用作輸入或者輸出,或者工作在半雙工模式下。
I2C
USART
Device Signature
1、 STM32F10xxx系列MCU內(nèi)部含有一個(gè)出廠被固化的96bit唯一識(shí)別ID,該ID可以用于芯片加密、設(shè)備識(shí)別等一類特殊應(yīng)用。
讀取該ID的方法:
u32 DevID[3];
DevID[0] *(vu32*)(0x1ffff7e8);
DevID[1] *(vu32*)(0x1ffff7ec);
DevID[2] *(vu32*)(0x1ffff7f0);
數(shù)組DevID[3]中即保存了MCU的ID。
注:256K Flash或以上容量的STM32,僅“Z”版本才有,之前的“A”版本沒(méi)有。
1、STM32對(duì)內(nèi)部Flash的保護(hù)措施
所有STM32的芯片都提供對(duì)Flash的保護(hù),防止對(duì)Flash的非法訪問(wèn) - 寫(xiě)保護(hù)和讀保護(hù)。
1)、讀保護(hù)即大家通常說(shuō)的“加密”,是作用于整個(gè)Flash存儲(chǔ)區(qū)域。一旦設(shè)置了Flash的讀保護(hù),內(nèi)置的Flash存儲(chǔ)區(qū)只能通過(guò)程序的正常執(zhí)行才能讀出,而不能通過(guò)下述任何一種方式讀出:
通過(guò)調(diào)試器(JTAG或SWD);
從RAM中啟動(dòng)并執(zhí)行的程序;
2)、寫(xiě)保護(hù)是以四頁(yè)(1KB/頁(yè)) Flash存儲(chǔ)區(qū)為單位提供寫(xiě)保護(hù),對(duì)被保護(hù)的頁(yè)實(shí)施編程或擦除操作將不被執(zhí)行,同時(shí)產(chǎn)生操作錯(cuò)誤標(biāo)志。
讀與寫(xiě)設(shè)置的效果見(jiàn)下表:
讀保護(hù) 寫(xiě)保護(hù) 對(duì)Flash的操作功能
有效 有效 CPU只能讀,禁止調(diào)試和非法訪問(wèn)。
有效 無(wú)效 CPU可以讀寫(xiě),禁止調(diào)試和非法訪問(wèn),頁(yè)0~3為寫(xiě)保護(hù)。
無(wú)效 有效 CPU可讀,允許調(diào)試和非法訪問(wèn)。
無(wú)效 無(wú)效 CPU可以讀寫(xiě),允許調(diào)試和非法訪問(wèn)。
2、當(dāng)Flash讀保護(hù)生效時(shí),CPU執(zhí)行程序可以讀受保護(hù)的Flash區(qū),但存在兩個(gè)例外情況:
1)、調(diào)試執(zhí)行程序時(shí);
2)、從RAM啟動(dòng)并執(zhí)行程序時(shí)
STM32還提供了一個(gè)特別的保護(hù),即對(duì)Flash存儲(chǔ)區(qū)施加讀保護(hù)后,即使沒(méi)有啟用寫(xiě)保護(hù),F(xiàn)lash的第 0 ~ 3 頁(yè)也將處于寫(xiě)保護(hù)狀態(tài),這是為了防止修改復(fù)位或中斷向量而跳轉(zhuǎn)到RAM區(qū)執(zhí)行非法程序代碼。
3、Flash保護(hù)相關(guān)函數(shù)
FLASH_Unlock(); //Flash解鎖
FLASH_ReadOutProtection(DISABLE); //Flash讀保護(hù)禁止
FLASH_ReadOutProtection(ENABLE); //Flash讀保護(hù)允許
CRC
1、CRC計(jì)算公式
所有的STM32芯片都內(nèi)置了一個(gè)硬件的CRC計(jì)算模塊,可應(yīng)用到通信程序中,這個(gè)CRC計(jì)算模塊使用常見(jiàn)的、在以太網(wǎng)中使用的計(jì)算多項(xiàng)式:
X32 + X26 + X23 + X22 + X16 + X12 + X11 + X10 +X8 + X7 + X5 + X4 + X2 + X + 1
寫(xiě)成16進(jìn)制就是:0x04C11DB7
2、使用這個(gè)內(nèi)置CRC模塊操作步驟:
復(fù)位CRC模塊(設(shè)置CRC_CR0x01),這個(gè)操作把CRC計(jì)算的余數(shù)初始化為0xFFFFFFFF
把要計(jì)算的數(shù)據(jù)按每32位分割為一組數(shù)據(jù)字,并逐個(gè)地把這組數(shù)據(jù)字寫(xiě)入CRC_DR寄存器(既下圖中的綠色框)
寫(xiě)完所有的數(shù)據(jù)字后,就可以從CRC_DR寄存器(既下圖中的蘭色框)讀出計(jì)算的結(jié)果。
注意:雖然讀寫(xiě)操作都是針對(duì)CRC_DR寄存器,但實(shí)際上是訪問(wèn)的不同物理寄存器。
3、C語(yǔ)言描述的這個(gè)計(jì)算模塊算法??煞旁谕ㄐ诺牧硪欢?,對(duì)通信的正確性進(jìn)行驗(yàn)證:
DWORD dwPolynomial 0x04c11db7;
DWORD cal_crc(DWORD *ptr, int len)
{
DWORD xbit;
DWORD data;
DWORD CRC 0xFFFFFFFF; // init
while (len--)
{
xbit 1 《《 31;
data *ptr++;
for (int bits 0; bits 《 32; bits++)
{
if (CRC & 0x80000000)
{
CRC 《《 1;
CRC ^ dwPolynomial;
}else
CRC 《《 1;
if (data & xbit)
CRC ^ dwPolynomial;
xbit 》》 1;
}
}
return CRC;
}
注意:
1)、上述算法中變量CRC,在每次循環(huán)結(jié)束包含了計(jì)算的余數(shù),它始終是向左移位(既從最低位向最高位移動(dòng)),溢出的數(shù)據(jù)位被丟棄。
2)、輸入的數(shù)據(jù)始終是以32位為單位,如果原始數(shù)據(jù)少于32位,需要在低位補(bǔ)0,當(dāng)然也可以高位補(bǔ)0。
3)、假定輸入的DWORD數(shù)組中每個(gè)分量是按小端存儲(chǔ)。
4)、輸入數(shù)據(jù)是按照最高位最先計(jì)算,最低位最后計(jì)算的順序進(jìn)行。
例如:
如果輸入0x44434241,內(nèi)存中按字節(jié)存放的順序是:0x41, 0x42, 0x43, 0x44。計(jì)算的結(jié)果是:0xCF534AE1
如果輸入0x41424344,內(nèi)存中按字節(jié)存放的順序是:0x44, 0x43, 0x42, 0x41。計(jì)算的結(jié)果是:0xABCF9A63
IAR
1、IAR環(huán)境下如果鏈接工程文件,出現(xiàn)堆棧溢出錯(cuò)誤,該如何處理?
打開(kāi)鏈接文件lnkarm_flash.xcl或者是lnkarm_ram.xcl
//*****************************
// Stack and heap segments.
//*****************************
-D_CSTACK_SIZE400 《---------------修改這里
注:該修改方式僅適合IAR for ARM 4.xx版本。
2、IAR編譯輸出HEX格式的目標(biāo)文件
1)、Options-》C/C++ Compiler-》Output-》Generate debug information 選項(xiàng)前的鉤去掉
2)、Options-》Assembler-》Output-》Generate debug information 選項(xiàng)前的鉤去掉
3)、Options-》Linker-》Output-》Output File-》Override default 選項(xiàng)前的鉤選上并把文件名的后綴改成.hex
4)、Options-》Linker-》Output-》Output File-》Format-》Other 選項(xiàng)前的鉤選上并把Output格式改為intel-extended
經(jīng)過(guò)以上設(shè)置,在Rebuld All之后會(huì)在/Debug/Exe下生成.hex格式目標(biāo)文件
3、IAR編譯輸出BIN格式的目標(biāo)文件
1)、Options-》C/C++ Compiler-》Output-》Generate debug information 選項(xiàng)前的鉤去掉
2)、Options-》Assembler-》Output-》Generate debug information 選項(xiàng)前的鉤去掉
3)、Options-》Linker-》Output-》Output File-》Override default 選項(xiàng)前的鉤選上并把文件名的后綴改成.bin
4)、Options-》Linker-》Output-》Output File-》Format-》Other 選項(xiàng)前的鉤選上并把Output格式改為row-binary
經(jīng)過(guò)以上設(shè)置,在Rebuld All之后會(huì)在/Debug/Exe下生成.bin格式目標(biāo)文件
1、在MDK代碼編輯環(huán)境下不能使用Goto Definition(用于查找某個(gè)變量的類型及定義)、Goto Reference(用于查找某個(gè)函數(shù)申明的原型)功能?
解決:打開(kāi)Project-》Target-Options-》Output,將Browse Information復(fù)選框勾上。
2、當(dāng)使用STM32固件庫(kù)與RTX Kernel時(shí),使用isr_evt_set(),事件無(wú)響應(yīng)?
解決:編輯STM32固件庫(kù)的“stm32f10x_vector.s”文件:
IMPORT SVC_Handler ;name changed according to RTX usage
IMPORT DebugMonitor
IMPORT PendSV_Handler ;修改加入
IMPORT SysTick_Handler ;name changed according to RTX usage
DCD SVC_Handler
DCD DebugMonitor
DCD 0 ; Reserved
DCD PendSV_Handler ;修改加入
DCD SysTick_Handler
評(píng)論
查看更多