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