stm32中断优先级分组
生活随笔
收集整理的這篇文章主要介紹了
stm32中断优先级分组
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
STM32中斷優(yōu)先級和開關(guān)總中斷一,中斷優(yōu)先級:STM32(Cortex-M3)中的優(yōu)先級概念
STM32(Cortex-M3)中有兩個(gè)優(yōu)先級的概念——搶占式優(yōu)先級和響應(yīng)優(yōu)先級,有人把響應(yīng)優(yōu)先級稱作'亞優(yōu)先級'或'副優(yōu)先級',每個(gè)中斷源都需要被指定這兩種優(yōu)先級。具有高搶占式優(yōu)先級的中斷可以在具有低搶占式優(yōu)先級的中斷處理過程中被響應(yīng),即中斷嵌套,或者說高搶占式優(yōu)先級的中斷可以嵌套低搶占式優(yōu)先級的中斷。當(dāng)兩個(gè)中斷源的搶占式優(yōu)先級相同時(shí),這兩個(gè)中斷將沒有嵌套關(guān)系,當(dāng)一個(gè)中斷到來后,如果正在處理另一個(gè)中斷,這個(gè)后到來的中斷就要等到前一個(gè)中斷處理完之后才能被處理。如果這兩個(gè)中斷同時(shí)到達(dá),則中斷控制器根據(jù)他們的響應(yīng)優(yōu)先級高低來決定先處理哪一個(gè);如果他們的搶占式優(yōu)先級和響應(yīng)優(yōu)先級都相等,則根據(jù)他們在中斷表中的排位順序決定先處理哪一個(gè)。既然每個(gè)中斷源都需要被指定這兩種優(yōu)先級,就需要有相應(yīng)的寄存器位記錄每個(gè)中斷的優(yōu)先級;在Cortex-M3中定義了8個(gè)比特位用于設(shè)置中斷源的優(yōu)先級,這8個(gè)比特位可以有8種分配方式,如下:所有8位用于指定響應(yīng)優(yōu)先級
最高1位用于指定搶占式優(yōu)先級,最低7位用于指定響應(yīng)優(yōu)先級
最高2位用于指定搶占式優(yōu)先級,最低6位用于指定響應(yīng)優(yōu)先級
最高3位用于指定搶占式優(yōu)先級,最低5位用于指定響應(yīng)優(yōu)先級
最高4位用于指定搶占式優(yōu)先級,最低4位用于指定響應(yīng)優(yōu)先級
最高5位用于指定搶占式優(yōu)先級,最低3位用于指定響應(yīng)優(yōu)先級
最高6位用于指定搶占式優(yōu)先級,最低2位用于指定響應(yīng)優(yōu)先級
最高7位用于指定搶占式優(yōu)先級,最低1位用于指定響應(yīng)優(yōu)先級這就是優(yōu)先級分組的概念。--------------------------------------------------------------------------------
Cortex-M3允許具有較少中斷源時(shí)使用較少的寄存器位指定中斷源的優(yōu)先級,因此STM32把指定中斷優(yōu)先級的寄存器位減少到4位,這4個(gè)寄存器位的分組方式如下: 第0組:所有4位用于指定響應(yīng)優(yōu)先級
第1組:最高1位用于指定搶占式優(yōu)先級,最低3位用于指定響應(yīng)優(yōu)先級
第2組:最高2位用于指定搶占式優(yōu)先級,最低2位用于指定響應(yīng)優(yōu)先級
第3組:最高3位用于指定搶占式優(yōu)先級,最低1位用于指定響應(yīng)優(yōu)先級
第4組:所有4位用于指定搶占式優(yōu)先級可以通過調(diào)用STM32的固件庫中的函數(shù)NVIC_PriorityGroupConfig()選擇使用哪種優(yōu)先級分組方式,這個(gè)函數(shù)的參數(shù)有下列5種:NVIC_PriorityGroup_0 => 選擇第0組
NVIC_PriorityGroup_1 => 選擇第1組
NVIC_PriorityGroup_2 => 選擇第2組
NVIC_PriorityGroup_3 => 選擇第3組
NVIC_PriorityGroup_4 => 選擇第4組 接下來就是指定中斷源的優(yōu)先級,下面以一個(gè)簡單的例子說明如何指定中斷源的搶占式優(yōu)先級和響應(yīng)優(yōu)先級:// 選擇使用優(yōu)先級分組第1組
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);// 使能EXTI0中斷
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 指定搶占式優(yōu)先級別1NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 指定響應(yīng)優(yōu)先級別0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);// 使能EXTI9_5中斷
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 指定搶占式優(yōu)先級別0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 指定響應(yīng)優(yōu)先級別1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);要注意的幾點(diǎn)是:1)如果指定的搶占式優(yōu)先級別或響應(yīng)優(yōu)先級別超出了選定的優(yōu)先級分組所限定的范圍,將可能得到意想不到的結(jié)果;2)搶占式優(yōu)先級別相同的中斷源之間沒有嵌套關(guān)系;3)如果某個(gè)中斷源被指定為某個(gè)搶占式優(yōu)先級別,又沒有其它中斷源處于同一個(gè)搶占式優(yōu)先級別,則可以為這個(gè)中斷源指定任意有效的響應(yīng)優(yōu)先級別。二,開關(guān)總中斷:在STM32/Cortex-M3中是通過改變CPU的當(dāng)前優(yōu)先級來允許或禁止中斷。
PRIMASK位:只允許NMI和hard fault異常,其他中斷/異常都被屏蔽(當(dāng)前CPU優(yōu)先級=0)。
FAULTMASK位:只允許NMI,其他所有中斷/異常都被屏蔽(當(dāng)前CPU優(yōu)先級=-1)。在STM32固件庫中(stm32f10x_nvic.c和stm32f10x_nvic.h) 定義了四個(gè)函數(shù)操作PRIMASK位和FAULTMASK位,改變CPU的當(dāng)前優(yōu)先級,從而達(dá)到控制所有中斷的目的。下面兩個(gè)函數(shù)等效于關(guān)閉總中斷:
void NVIC_SETPRIMASK(void);
void NVIC_SETFAULTMASK(void);下面兩個(gè)函數(shù)等效于開放總中斷:
void NVIC_RESETPRIMASK(void);
void NVIC_RESETFAULTMASK(void);上面兩組函數(shù)要成對使用,不能交叉使用。例如:第一種方法:
NVIC_SETPRIMASK(); //關(guān)閉總中斷
NVIC_RESETPRIMASK();//開放總中斷第二種方法:
NVIC_SETFAULTMASK(); //關(guān)閉總中斷
NVIC_RESETFAULTMASK();//開放總中斷常常使用NVIC_SETPRIMASK(); // Disable Interrupts
NVIC_RESETPRIMASK(); // Enable InterruptsSTM32時(shí)鐘系統(tǒng)STM32資料 2009-09-23 14:53 閱讀72 評論0
字號: 大大 中中 小小
在STM32中,有五個(gè)時(shí)鐘源,為HSI、HSE、LSI、LSE、PLL。①、HSI是高速內(nèi)部時(shí)鐘,RC振蕩器,頻率為8MHz。②、HSE是高速外部時(shí)鐘,可接石英/陶瓷諧振器,或者接外部時(shí)鐘源,頻率范圍為4MHz~16MHz。③、LSI是低速內(nèi)部時(shí)鐘,RC振蕩器,頻率為40kHz。④、LSE是低速外部時(shí)鐘,接頻率為32.768kHz的石英晶體。⑤、PLL為鎖相環(huán)倍頻輸出,其時(shí)鐘輸入源可選擇為HSI/2、HSE或者HSE/2。倍頻可選擇為2~16倍,但是其輸出頻率最大不得超過72MHz。圖1 HSE/LSE時(shí)鐘源其中40kHz的LSI供獨(dú)立看門狗IWDG使用,另外它還可以被選擇為實(shí)時(shí)時(shí)鐘RTC的時(shí)鐘源。另外,實(shí)時(shí)時(shí)鐘RTC的時(shí)鐘源還可以選擇LSE,或者是HSE的128分頻。RTC的時(shí)鐘源通過RTCSEL[1:0]來選擇。STM32中有一個(gè)全速功能的USB模塊,其串行接口引擎需要一個(gè)頻率為48MHz的時(shí)鐘源。該時(shí)鐘源只能從PLL輸出端獲取,可以選擇為1.5分頻或者1分頻,也就是,當(dāng)需要使用USB模塊時(shí),PLL必須使能,并且時(shí)鐘頻率配置為48MHz或72MHz。另外,STM32還可以選擇一個(gè)時(shí)鐘信號輸出到MCO腳(PA8)上,可以選擇為PLL輸出的2分頻、HSI、HSE、或者系統(tǒng)時(shí)鐘。系統(tǒng)時(shí)鐘SYSCLK,它是供STM32中絕大部分部件工作的時(shí)鐘源。系統(tǒng)時(shí)鐘可選擇為PLL輸出、HSI或者HSE。系統(tǒng)時(shí)鐘最大頻率為72MHz,它通過AHB分頻器分頻后送給各模塊使用,AHB分頻器可選擇1、2、4、8、16、64、128、256、512分頻。其中AHB分頻器輸出的時(shí)鐘送給5大模塊使用:①、送給AHB總線、內(nèi)核、內(nèi)存和DMA使用的HCLK時(shí)鐘。②、通過8分頻后送給Cortex的系統(tǒng)定時(shí)器時(shí)鐘。③、直接送給Cortex的空閑運(yùn)行時(shí)鐘FCLK。④、送給APB1分頻器。APB1分頻器可選擇1、2、4、8、16分頻,其輸出一路供APB1外設(shè)使用(PCLK1,最大頻率36MHz),另一路送給定時(shí)器(Timer)2、3、4倍頻器使用。該倍頻器可選擇1或者2倍頻,時(shí)鐘輸出供定時(shí)器2、3、4使用。⑤、送給APB2分頻器。APB2分頻器可選擇1、2、4、8、16分頻,其輸出一路供APB2外設(shè)使用(PCLK2,最大頻率72MHz),另一路送給定時(shí)器(Timer)1倍頻器使用。該倍頻器可選擇1或者2倍頻,時(shí)鐘輸出供定時(shí)器1使用。另外,APB2分頻器還有一路輸出供ADC分頻器使用,分頻后送給ADC模塊使用。ADC分頻器可選擇為2、4、6、8分頻。在以上的時(shí)鐘輸出中,有很多是帶使能控制的,例如AHB總線時(shí)鐘、內(nèi)核時(shí)鐘、各種APB1外設(shè)、APB2外設(shè)等等。當(dāng)需要使用某模塊時(shí),記得一定要先使能對應(yīng)的時(shí)鐘。需要注意的是定時(shí)器的倍頻器,當(dāng)APB的分頻為1時(shí),它的倍頻值為1,否則它的倍頻值就為2。連接在APB1(低速外設(shè))上的設(shè)備有:電源接口、備份接口、CAN、USB、I2C1、I2C2、UART2、UART3、SPI2、窗口看門狗、Timer2、Timer3、Timer4。注意USB模塊雖然需要一個(gè)單獨(dú)的48MHz時(shí)鐘信號,但它應(yīng)該不是供USB模塊工作的時(shí)鐘,而只是提供給串行接口引擎(SIE)使用的時(shí)鐘。USB模塊工作的時(shí)鐘應(yīng)該是由APB1提供的。連接在APB2(高速外設(shè))上的設(shè)備有:UART1、SPI1、Timer1、ADC1、ADC2、所有普通IO口(PA~PE)、第二功能IO口。下圖是STM32用戶手冊中的時(shí)鐘系統(tǒng)結(jié)構(gòu)圖,通過該圖可以從總體上掌握STM32的時(shí)鐘系統(tǒng)。STM32外部中斷之二STM32資料 2009-09-10 21:18 閱讀243 評論0
字號: 大大 中中 小小
STM32 外部中斷配置1配置中斷1、 分配中斷向量表:/* Set the Vector Table base location at 0x20000000 */ NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);2、 設(shè)置中斷優(yōu)先級:NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); //設(shè)置中斷優(yōu)先級3、 初始化外部中斷:/*允許EXTI4中斷 */NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQChannel; //中斷通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = PreemptionPriorityValue;//強(qiáng)占優(yōu)先級NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //次優(yōu)先級NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //通道中斷使能NVIC_Init(&NVIC_InitStructure); //初始化中斷注意:如果我們配置的外部針腳為PA4,或PB4,或PC4,PD4等,那么采用的外部中斷也必須是EXTI4,同樣,如果外部中斷針腳是PA1,PB1,PC1,PD1 那么中斷就要用EXTI1,其他類推。2配置GPIO針腳作為外部中斷的觸發(fā)事件 1、 選擇IO針腳GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;注意,如果的針腳是端口的4號針腳,配置的中斷一定是EXTI42、 配置針腳為輸入GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;3、 初始化針腳GPIO_Init(GPIOD,&GPIO_InitStructure);3配置EXTI線,使中斷線和IO針腳線連接上1、 將EXTI線連接到IO端口上將EXTI線4連接到端口GPIOD的第4個(gè)針腳上GPIO_EXTILineConfig(GPIO_PortSourceGPIOD,GPIO_PinSource4);注意:如果配置的針腳是4號,那么參數(shù)必須是GPIO_PinSource4如果配置的針腳是3號,那么參數(shù)必須是GPIO_PinSource32、配置中斷邊沿/*配置EXTI線0上出現(xiàn)下降沿,則產(chǎn)生中斷*/EXTI_InitStructure.EXTI_Line = EXTI_Line4;注意:如果配置的4號針腳,那么EXTI_Line4是必須的EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿觸發(fā)EXTI_InitStructure.EXTI_LineCmd = ENABLE; //中斷線使能EXTI_Init(&EXTI_InitStructure); //初始化中斷EXTI_GenerateSWInterrupt(EXTI_Line4); //EXTI_Line4中斷允許到此中斷配置完成,可以寫中斷處理函數(shù)。舉例:配置函數(shù)/************************************************************************** 函數(shù)名 NVIC_Configration* 描述 配置各個(gè)中斷寄存器* 輸入 無 * 輸出 無* 返回值 無****************************************************************************/void NVIC_Configration(void){NVIC_InitTypeDef NVIC_InitStructure; //#ifdef VECT_TAB_RAM /* Set the Vector Table base location at 0x20000000 */ NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); //#else /* VECT_TAB_FLASH *//* Set the Vector Table base location at 0x08000000 */ //NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); //#endif NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); //設(shè)置中斷優(yōu)先級/*允許EXTI4中斷 */NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQChannel;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = PreemptionPriorityValue;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure); /*允許EXTI9中斷*/NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQChannel;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure); /*配置SysTick處理優(yōu)先級:優(yōu)先級以及子優(yōu)先級*/}/************************************************************************* 函數(shù)名 :GPIO_Configuration(void)* 描述 :配置TIM2陣腳* 輸入 :無* 輸出 :無* 返回 :無************************************************************************/void GPIO_Configuration(void){/* GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure); */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;GPIO_Init(GPIOC,&GPIO_InitStructure);/*配置GPIOD的第一個(gè)管角為浮動輸入*/GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOD,&GPIO_InitStructure);/*配置GPIOB的第9個(gè)管腳為浮動輸入*/GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOB,&GPIO_InitStructure); }/*************************************************************** 函數(shù) SysTick_Configuration* 描述 設(shè)置SysTick* 輸入 無* 輸出 無* 返回值 無***************************************************************/void SysTick_Configuration(void){/*配置 HCLK 時(shí)鐘做為SysTick 時(shí)鐘源*/SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //系統(tǒng)時(shí)鐘8分頻 72MHzNVIC_SystemHandlerPriorityConfig(SystemHandler_SysTick, 8,2);/*SysTick Interrupt each 1000Hz with HCLK equal to 72MHz*/SysTick_SetReload(9000);//中斷周期1ms/*Enable the SysTick Interrupt */SysTick_ITConfig(ENABLE);//打開中斷 SysTick_CounterCmd(SysTick_Counter_Enable);SysTick_CounterCmd(SysTick_Counter_Clear); }/******************************************************************************* 函數(shù)名 EXTI_Configuration* 描述 配置EXTI線* 輸入 無 * 輸出 無* 返回值 無******************************************************************************/void EXTI_Configuration(void){/*將EXTI線0連接到PA0*/GPIO_EXTILineConfig(GPIO_PortSourceGPIOD,GPIO_PinSource4);/*配置EXTI線0上出現(xiàn)下降沿,則產(chǎn)生中斷*/EXTI_InitStructure.EXTI_Line = EXTI_Line4;EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;EXTI_InitStructure.EXTI_LineCmd = ENABLE;EXTI_Init(&EXTI_InitStructure);EXTI_GenerateSWInterrupt(EXTI_Line4);/*將EXTI線9連接到PB9上*/GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource9);/*將EXTI線9上出現(xiàn)下降沿產(chǎn)生中斷*/EXTI_InitStructure.EXTI_Line = EXTI_Line9;EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;EXTI_InitStructure.EXTI_LineCmd = ENABLE;EXTI_Init(&EXTI_InitStructure);EXTI_GenerateSWInterrupt(EXTI_Line9); }中斷函數(shù):void EXTI4_IRQHandler(void){if(EXTI_GetITStatus(EXTI_Line4)!= RESET){EXTI_ClearITPendingBit(EXTI_Line4);if(Ledflag == 0){Ledflag = 1;GPIOC->ODR |= 0X00000080;}else{Ledflag = 0; GPIOC->ODR &= 0XFFFFFF7F;}}}注:時(shí)鐘設(shè)置的時(shí)候最好加上這句: RCCRCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); // 使能AFIO時(shí)鐘STM32中定時(shí)器的時(shí)鐘源STM32資料 2009-07-24 21:34 閱讀277 評論0
字號: 大大 中中 小小 STM32中有多達(dá)8個(gè)定時(shí)器,其中TIM1和TIM8是能夠產(chǎn)生三對PWM互補(bǔ)輸出的高級定時(shí)器,常用于三相電機(jī)的驅(qū)動,它們的時(shí)鐘由APB2的輸出產(chǎn)生。其它6個(gè)為普通定時(shí)器,時(shí)鐘由APB1的輸出產(chǎn)生。下圖是STM32參考手冊上時(shí)鐘分配圖中,有關(guān)定時(shí)器時(shí)鐘部分的截圖:從圖中可以看出,定時(shí)器的時(shí)鐘不是直接來自APB1或APB2,而是來自于輸入為APB1或APB2的一個(gè)倍頻器,圖中的藍(lán)色部分。下面以定時(shí)器2~7的時(shí)鐘說明這個(gè)倍頻器的作用:當(dāng)APB1的預(yù)分頻系數(shù)為1時(shí),這個(gè)倍頻器不起作用,定時(shí)器的時(shí)鐘頻率等于APB1的頻率;當(dāng)APB1的預(yù)分頻系數(shù)為其它數(shù)值(即預(yù)分頻系數(shù)為2、4、8或16)時(shí),這個(gè)倍頻器起作用,定時(shí)器的時(shí)鐘頻率等于APB1的頻率兩倍。假定AHB=36MHz,因?yàn)锳PB1允許的最大頻率為36MHz,所以APB1的預(yù)分頻系數(shù)可以取任意數(shù)值;當(dāng)預(yù)分頻系數(shù)=1時(shí),APB1=36MHz,TIM2~7的時(shí)鐘頻率=36MHz(倍頻器不起作用);當(dāng)預(yù)分頻系數(shù)=2時(shí),APB1=18MHz,在倍頻器的作用下,TIM2~7的時(shí)鐘頻率=36MHz。有人會問,既然需要TIM2~7的時(shí)鐘頻率=36MHz,為什么不直接取APB1的預(yù)分頻系數(shù)=1?答案是:APB1不但要為TIM2~7提供時(shí)鐘,而且還要為其它外設(shè)提供時(shí)鐘;設(shè)置這個(gè)倍頻器可以在保證其它外設(shè)使用較低時(shí)鐘頻率時(shí),TIM2~7仍能得到較高的時(shí)鐘頻率。再舉個(gè)例子:當(dāng)AHB=72MHz時(shí),APB1的預(yù)分頻系數(shù)必須大于2,因?yàn)锳PB1的最大頻率只能為36MHz。如果APB1的預(yù)分頻系數(shù)=2,則因?yàn)檫@個(gè)倍頻器,TIM2~7仍然能夠得到72MHz的時(shí)鐘頻率。能夠使用更高的時(shí)鐘頻率,無疑提高了定時(shí)器的分辨率,這也正是設(shè)計(jì)這個(gè)倍頻器的初衷。STM32筆記之外部中斷GPIOSTM32資料 2009-07-14 13:35 閱讀331 評論0
字號: 大大 中中 小小
b) 初始化函數(shù)定義:
void EXTI_Configuration(void); //定義IO中斷初始化函數(shù)
c) 初始化函數(shù)調(diào)用:
EXTI_Configuration();//IO中斷初始化函數(shù)調(diào)用簡單應(yīng)用:
d) 初始化函數(shù):
void EXTI_Configuration(void)
{EXTI_InitTypeDef EXTI_InitStructure; //EXTI初始化結(jié)構(gòu)定義EXTI_ClearITPendingBit(EXTI_LINE_KEY_BUTTON);//清除中斷標(biāo)志GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource3);//管腳選擇GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource4);GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource5);GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource6);EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//事件選擇EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//觸發(fā)模式EXTI_InitStructure.EXTI_Line = EXTI_Line3 | EXTI_Line4; //線路選擇EXTI_InitStructure.EXTI_LineCmd = ENABLE;//啟動中斷EXTI_Init(&EXTI_InitStructure);//初始化
}e) RCC初始化函數(shù)中開啟I/O時(shí)鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);GPIO初始化函數(shù)中定義輸入I/O管腳。
//IO輸入,GPIOA的4腳輸入GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉輸入GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化
f) 在NVIC的初始化函數(shù)里面增加以下代碼打開相關(guān)中斷:NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQChannel; //通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//占先級NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //響應(yīng)級NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //啟動NVIC_Init(&NVIC_InitStructure); //初始化g) 在stm32f10x_it.c文件中找到void USART1_IRQHandler函數(shù),在其中添入執(zhí)行代碼。一般最少三個(gè)步驟:先使用if語句判斷是發(fā)生那個(gè)中斷,然后清除中斷標(biāo)志位,最后給字符串賦值,或做其他事情。if(EXTI_GetITStatus(EXTI_Line3) != RESET) //判斷中斷發(fā)生來源{ EXTI_ClearITPendingBit(EXTI_Line3); //清除中斷標(biāo)志USART_SendData(USART1, 0x41); //發(fā)送字符“a”GPIO_WriteBit(GPIOB, GPIO_Pin_2, (BitAction)(1-GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_2)));//LED發(fā)生明暗交替
}
h) 中斷注意事項(xiàng):
中斷發(fā)生后必須清除中斷位,否則會出現(xiàn)死循環(huán)不斷發(fā)生這個(gè)中斷。然后需要對中斷類型進(jìn)行判斷再執(zhí)行代碼。
使用EXTI的I/O中斷,在完成RCC與GPIO硬件設(shè)置之后需要做三件事:初始化EXTI、NVIC開中斷、編寫中斷執(zhí)行代碼。 STM32的USARTSTM32資料 2009-07-14 13:33 閱讀489 評論4
字號: 大大 中中 小小
b) 初始化函數(shù)定義:
void USART_Configuration(void); //定義串口初始化函數(shù)
c) 初始化函數(shù)調(diào)用:
void UART_Configuration(void); //串口初始化函數(shù)調(diào)用
初始化代碼:
void USART_Configuration(void) //串口初始化函數(shù)
{
//串口參數(shù)初始化 USART_InitTypeDef USART_InitStructure; //串口設(shè)置恢復(fù)默認(rèn)參數(shù)//初始化參數(shù)設(shè)置USART_InitStructure.USART_BaudRate = 9600; //波特率9600USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字長8位USART_InitStructure.USART_StopBits = USART_StopBits_1; //1位停止字節(jié)USART_InitStructure.USART_Parity = USART_Parity_No; //無奇偶校驗(yàn)USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//無流控制USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//打開Rx接收和Tx發(fā)送功能USART_Init(USART1, &USART_InitStructure); //初始化USART_Cmd(USART1, ENABLE); //啟動串口
}RCC中打開相應(yīng)串口
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 , ENABLE);GPIO里面設(shè)定相應(yīng)串口管腳模式
//串口1的管腳初始化 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //管腳9GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復(fù)用推挽輸出GPIO_Init(GPIOA, &GPIO_InitStructure); //TX初始化GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //管腳10GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空輸入GPIO_Init(GPIOA, &GPIO_InitStructure); //RX初始化d) 簡單應(yīng)用:
發(fā)送一位字符
USART_SendData(USART1, 數(shù)據(jù)); //發(fā)送一位數(shù)據(jù)
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET){} //等待發(fā)送完畢
接收一位字符
while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET){} //等待接收完畢
變量= (USART_ReceiveData(USART1)); //接受一個(gè)字節(jié)發(fā)送一個(gè)字符串先定義字符串:char rx_data[250];然后在需要發(fā)送的地方添加如下代碼int i; //定義循環(huán)變量while(rx_data!='\0') //循環(huán)逐字輸出,到結(jié)束字'\0'{USART_SendData(USART1, rx_data); //發(fā)送字符while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET){} //等待字符發(fā)送完畢i++;} e) USART注意事項(xiàng):
發(fā)動和接受都需要配合標(biāo)志等待。
只能對一個(gè)字節(jié)操作,對字符串等大量數(shù)據(jù)操作需要寫函數(shù)使用串口所需設(shè)置:RCC初始化里面打開RCC_APB2PeriphClockCmd
(RCC_APB2Periph_USARTx);GPIO里面管腳設(shè)定:串口RX(50Hz,IN_FLOATING);串口TX(50Hz,AF_PP); f) printf函數(shù)重定義(不必理解,調(diào)試通過以備后用)
(1) 需要c標(biāo)準(zhǔn)函數(shù):
#include "stdio.h"
(2) 粘貼函數(shù)定義代碼
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch) //定義為putchar應(yīng)用
(3) RCC中打開相應(yīng)串口
(4) GPIO里面設(shè)定相應(yīng)串口管腳模式
(6) 增加為putchar函數(shù)。
int putchar(int c) //putchar函數(shù)
{if (c == '\n'){putchar('\r');} //將printf的\n變成\rUSART_SendData(USART1, c); //發(fā)送字符while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET){} //等待發(fā)送結(jié)束return c; //返回值
}(8) 通過,試驗(yàn)成功。printf使用變量輸出:%c字符,%d整數(shù),%f浮點(diǎn)數(shù),%s字符串,/n或/r為換行。注意:只能用于main.c中。3、 NVIC串口中斷的應(yīng)用
a) 目的:利用前面調(diào)通的硬件基礎(chǔ),和幾個(gè)函數(shù)的代碼,進(jìn)行串口的中斷輸入練習(xí)。因?yàn)樵趯?shí)際應(yīng)用中,不使用中斷進(jìn)行的輸入是效率非常低的,這種用法很少見,大部分串口的輸入都離不開中斷。
b) 初始化函數(shù)定義及函數(shù)調(diào)用:不用添加和調(diào)用初始化函數(shù),在指定調(diào)試地址的時(shí)候已經(jīng)調(diào)用過,在那個(gè)NVIC_Configuration里面添加相應(yīng)開中斷代碼就行了。
c) 過程:
i. 在串口初始化中USART_Cmd之前加入中斷設(shè)置:
USART_ITConfig(USART1, USART_IT_TXE, ENABLE);//TXE發(fā)送中斷,TC傳輸完成中斷,RXNE接收中斷,PE奇偶錯誤中斷,可以是多個(gè)。
ii. RCC、GPIO里面打開串口相應(yīng)的基本時(shí)鐘、管腳設(shè)置
iii. NVIC里面加入串口中斷打開代碼:
NVIC_InitTypeDef NVIC_InitStructure;//中斷默認(rèn)參數(shù)NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQChannel;//通道設(shè)置為串口1中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //中斷占先等級0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //中斷響應(yīng)優(yōu)先級0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //打開中斷
NVIC_Init(&NVIC_InitStructure); //初始化iv. 在stm32f10x_it.c文件中找到void USART1_IRQHandler函數(shù),在其中添入執(zhí)行代碼。一般最少三個(gè)步驟:先使用if語句判斷是發(fā)生那個(gè)中斷,然后清除中斷標(biāo)志位,最后給字符串賦值,或做其他事情。
void USART1_IRQHandler(void) //串口1中斷
{
char RX_dat; //定義字符變量if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //判斷發(fā)生接收中斷{USART_ClearITPendingBit(USART1, USART_IT_RXNE); //清除中斷標(biāo)志GPIO_WriteBit(GPIOB, GPIO_Pin_10, (BitAction)0x01); //開始傳輸RX_dat=USART_ReceiveData(USART1) & 0x7F; //接收數(shù)據(jù),整理除去前兩位USART_SendData(USART1, RX_dat); //發(fā)送數(shù)據(jù)while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET){}//等待發(fā)送結(jié)束}
}d) 中斷注意事項(xiàng):
可以隨時(shí)在程序中使用USART_ITConfig(USART1, USART_IT_TXE, DISABLE);來關(guān)閉中斷響應(yīng)。
NVIC_InitTypeDef NVIC_InitStructure定義一定要加在NVIC初始化模塊的第一句。
全局變量與函數(shù)的定義:在任意.c文件中定義的變量或函數(shù),在其它.c文件中使用extern+定義代碼再次定義就可以直接調(diào)用了。 STM32運(yùn)行的必要硬件庫STM32資料 2009-07-14 13:31 閱讀163 評論0
字號: 大大 中中 小小
0、 實(shí)驗(yàn)之前的準(zhǔn)備
a) 接通串口轉(zhuǎn)接器
b) 下載IO與串口的原廠程序,編譯通過保證調(diào)試所需硬件正常。1、 flash,lib,nvic,rcc和GPIO,基礎(chǔ)程序庫編寫
a) 這幾個(gè)庫函數(shù)中有一些函數(shù)是關(guān)于芯片的初始化的,每個(gè)程序中必用。為保障程序品質(zhì),初學(xué)階段要求嚴(yán)格遵守官方習(xí)慣。注意,官方程序庫例程中有個(gè)platform_config.h文件,是專門用來指定同類外設(shè)中第幾號外設(shè)被使用,就是說在main.c里面所有外設(shè)序號用x代替,比如USARTx,程序會到這個(gè)頭文件中去查找到底是用那些外設(shè),初學(xué)的時(shí)候參考例程別被這個(gè)所迷惑住。
b) 全部必用代碼取自庫函數(shù)所帶例程,并增加逐句注釋。
c) 習(xí)慣順序——Lib(debug),RCC(包括Flash優(yōu)化),NVIC,GPIO
d) 必用模塊初始化函數(shù)的定義:
void RCC_Configuration(void); //定義時(shí)鐘初始化函數(shù)
void GPIO_Configuration(void); //定義管腳初始化函數(shù)
void NVIC_Configuration(void); //定義中斷管理初始化函數(shù)
void Delay(vu32 nCount); //定義延遲函數(shù)
e) Main中的初始化函數(shù)調(diào)用:
RCC_Configuration(); //時(shí)鐘初始化函數(shù)調(diào)用
NVIC_Configuration(); //中斷初始化函數(shù)調(diào)用
GPIO_Configuration(); //管腳初始化函數(shù)調(diào)用
f) Lib注意事項(xiàng):
屬于Lib的Debug函數(shù)的調(diào)用,應(yīng)該放在main函數(shù)最開始,不要改變其位置。g) RCC注意事項(xiàng):
Flash優(yōu)化處理可以不做,但是兩句也不難也不用改參數(shù)……
根據(jù)需要開啟設(shè)備時(shí)鐘可以節(jié)省電能
時(shí)鐘頻率需要根據(jù)實(shí)際情況設(shè)置參數(shù)
h) NVIC注意事項(xiàng)
注意理解占先優(yōu)先級和響應(yīng)優(yōu)先級的分組的概念
i) GPIO注意事項(xiàng)
注意以后的過程中收集不同管腳應(yīng)用對應(yīng)的頻率和模式的設(shè)置。作為高低電平的I/O,所需設(shè)置:RCC初始化里面打開RCC_APB2
PeriphClockCmd(RCC_APB2Periph_GPIOA);GPIO里面管腳設(shè)定:IO輸出(50MHz,Out_PP);IO輸入(50MHz,IPU);j) GPIO應(yīng)用
GPIO_WriteBit(GPIOB, GPIO_Pin_2, Bit_RESET);//重置
GPIO_WriteBit(GPIOB, GPIO_Pin_2, (BitAction)0x01);//寫入1
GPIO_WriteBit(GPIOB, GPIO_Pin_2, (BitAction)0x00);//寫入0
GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6) ;//讀入IO
k) 簡單Delay函數(shù)
void Delay(vu32 nCount)//簡單延時(shí)函數(shù)
{for(; nCount != 0; nCount--);} 基于STM32的PWM輸出STM32資料 2009-07-14 13:30 閱讀449 評論2
字號: 大大 中中 小小
c) 初始化函數(shù)定義:
void TIM_Configuration(void); //定義TIM初始化函數(shù)
d) 初始化函數(shù)調(diào)用:
TIM_Configuration(); //TIM初始化函數(shù)調(diào)用
e) 初始化函數(shù),不同于前面模塊,TIM的初始化分為兩部分——基本初始化和通道初始化:
void TIM_Configuration(void)//TIM初始化函數(shù)
{ TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;//定時(shí)器初始化結(jié)構(gòu)TIM_OCInitTypeDef TIM_OCInitStructure;//通道輸出初始化結(jié)構(gòu)//TIM3初始化TIM_TimeBaseStructure.TIM_Period = 0xFFFF; //周期0~FFFFTIM_TimeBaseStructure.TIM_Prescaler = 5; //時(shí)鐘分頻TIM_TimeBaseStructure.TIM_ClockDivision = 0; //時(shí)鐘分割TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//模式TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //基本初始化TIM_ITConfig(TIM3, TIM_IT_CC4, ENABLE);//打開中斷,中斷需要這行代碼//TIM3通道初始化TIM_OCStructInit(& TIM_OCInitStructure); //默認(rèn)參數(shù)TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //工作狀態(tài)TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //設(shè)定為輸出,需要PWM輸出才需要這行代碼TIM_OCInitStructure.TIM_Pulse = 0x2000; //占空長度TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //高電平TIM_OC4Init(TIM3, &TIM_OCInitStructure); //通道初始化TIM_Cmd(TIM3, ENABLE); //啟動TIM3
}f) RCC初始化函數(shù)中加入TIM時(shí)鐘開啟:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM3, ENABLE);
g) GPIO里面將輸入和輸出管腳模式進(jìn)行設(shè)置。信號:AF_PP,50MHz。
h) 使用中斷的話在NVIC里添加如下代碼://打開TIM2中斷NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQChannel; //通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;//占先級NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //響應(yīng)級NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //啟動NVIC_Init(&NVIC_InitStructure); //初始化中斷代碼:
void TIM2_IRQHandler(void)
{if (TIM_GetITStatus(TIM2, TIM_IT_CC4) != RESET) //判斷中斷來源{TIM_ClearITPendingBit(TIM2, TIM_IT_CC4); //清除中斷標(biāo)志GPIO_WriteBit(GPIOB, GPIO_Pin_11, (BitAction)(1-GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_11)));//變換LED色彩IC4value = TIM_GetCapture4(TIM2); //獲取捕捉數(shù)值}
}i) 簡單應(yīng)用:
//改變占空比
TIM_SetCompare4(TIM3, 變量);j) 注意事項(xiàng):
管腳的IO輸出模式是根據(jù)應(yīng)用來定,比如如果用PWM輸出驅(qū)動LED則應(yīng)該將相應(yīng)管腳設(shè)為AF_PP,否則單片機(jī)沒有輸出。 STM32資料一(轉(zhuǎn)載)STM32資料 2009-06-14 20:15 閱讀766 評論1
字號: 大大 中中 小小 注:下面是一些常用的代碼,網(wǎng)上很多但是大多注釋不全。高手看沒問題,對于我們這些新手就費(fèi)勁了……所以我把這些代碼集中,進(jìn)行了逐句注釋,希望對新手們有價(jià)值。閱讀flash: 芯片內(nèi)部存儲器flash操作函數(shù)我的理解——對芯片內(nèi)部flash進(jìn)行操作的函數(shù),包括讀取,狀態(tài),擦除,寫入等等,可以允許程序去操作flash上的數(shù)據(jù)。基礎(chǔ)應(yīng)用1,FLASH時(shí)序延遲幾個(gè)周期,等待總線同步操作。推薦按照單片機(jī)系統(tǒng)運(yùn)行頻率,0—24MHz時(shí),取Latency=0;24—48MHz時(shí),取Latency=1;48~72MHz時(shí),取Latency=2。所有程序中必須的用法:FLASH_SetLatency(FLASH_Latency_2);位置:RCC初始化子函數(shù)里面,時(shí)鐘起振之后。基礎(chǔ)應(yīng)用2,開啟FLASH預(yù)讀緩沖功能,加速FLASH的讀取。所有程序中必須的用法:FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);位置:RCC初始化子函數(shù)里面,時(shí)鐘起振之后。3、 閱讀lib:調(diào)試所有外設(shè)初始化的函數(shù)。我的理解——不理解,也不需要理解。只要知道所有外設(shè)在調(diào)試的時(shí)候,EWRAM需要從這個(gè)函數(shù)里面獲得調(diào)試所需信息的地址或者指針之類的信息。基礎(chǔ)應(yīng)用1,只有一個(gè)函數(shù)debug。所有程序中必須的。用法: #ifdef DEBUGdebug();#endif位置:main函數(shù)開頭,聲明變量之后。4、 閱讀nvic:系統(tǒng)中斷管理。我的理解——管理系統(tǒng)內(nèi)部的中斷,負(fù)責(zé)打開和關(guān)閉中斷。基礎(chǔ)應(yīng)用1,中斷的初始化函數(shù),包括設(shè)置中斷向量表位置,和開啟所需的中斷兩部分。所有程序中必須的。用法: void NVIC_Configuration(void){NVIC_InitTypeDef NVIC_InitStructure; //中斷管理恢復(fù)默認(rèn)參數(shù)#ifdef VECT_TAB_RAM //如果C/C++ Compiler\Preprocessor\Defined symbols中的定義了VECT_TAB_RAM(見程序庫更改內(nèi)容的表格)NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); //則在RAM調(diào)試#else //如果沒有定義VECT_TAB_RAMNVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);//則在Flash里調(diào)試#endif //結(jié)束判斷語句//以下為中斷的開啟過程,不是所有程序必須的。//NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //設(shè)置NVIC優(yōu)先級分組,方式。//注:一共16個(gè)優(yōu)先級,分為搶占式和響應(yīng)式。兩種優(yōu)先級所占的數(shù)量由此代碼確定,NVIC_PriorityGroup_x可以是0、1、2、3、4,分別代表搶占優(yōu)先級有1、2、4、8、16個(gè)和響應(yīng)優(yōu)先級有16、8、4、2、1個(gè)。規(guī)定兩種優(yōu)先級的數(shù)量后,所有的中斷級別必須在其中選擇,搶占級別高的會打斷其他中斷優(yōu)先執(zhí)行,而響應(yīng)級別高的會在其他中斷執(zhí)行完優(yōu)先執(zhí)行。//NVIC_InitStructure.NVIC_IRQChannel = 中斷通道名; //開中斷,中斷名稱見函數(shù)庫//NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //搶占優(yōu)先級//NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //響應(yīng)優(yōu)先級//NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //啟動此通道的中斷//NVIC_Init(&NVIC_InitStructure); //中斷初始化}5、 閱讀rcc:單片機(jī)時(shí)鐘管理。我的理解——管理外部、內(nèi)部和外設(shè)的時(shí)鐘,設(shè)置、打開和關(guān)閉這些時(shí)鐘。基礎(chǔ)應(yīng)用1:時(shí)鐘的初始化函數(shù)過程——用法:void RCC_Configuration(void) //時(shí)鐘初始化函數(shù){ErrorStatus HSEStartUpStatus; //等待時(shí)鐘的穩(wěn)定RCC_DeInit(); //時(shí)鐘管理重置RCC_HSEConfig(RCC_HSE_ON); //打開外部晶振HSEStartUpStatus = RCC_WaitForHSEStartUp(); //等待外部晶振就緒if (HSEStartUpStatus == SUCCESS){FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);//flash讀取緩沖,加速FLASH_SetLatency(FLASH_Latency_2); //flash操作的延時(shí)RCC_HCLKConfig(RCC_SYSCLK_Div1); //AHB使用系統(tǒng)時(shí)鐘RCC_PCLK2Config(RCC_HCLK_Div2); //APB2(高速)為HCLK的一半RCC_PCLK1Config(RCC_HCLK_Div2); //APB1(低速)為HCLK的一半//注:AHB主要負(fù)責(zé)外部存儲器時(shí)鐘。PB2負(fù)責(zé)AD,I/O,高級TIM,串口1。APB1負(fù)責(zé)DA,USB,SPI,I2C,CAN,串口2345,普通TIM。RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); //PLLCLK = 8MHz * 9 = 72 MHRCC_PLLCmd(ENABLE); //啟動PLLwhile (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET){} //等待PLL啟動RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //將PLL設(shè)置為系統(tǒng)時(shí)鐘源while (RCC_GetSYSCLKSource() != 0x08){} //等待系統(tǒng)時(shí)鐘源的啟動}//RCC_AHBPeriphClockCmd(ABP2設(shè)備1 | ABP2設(shè)備2 |, ENABLE); //啟動AHP設(shè)備//RCC_APB2PeriphClockCmd(ABP2設(shè)備1 | ABP2設(shè)備2 |, ENABLE);//啟動ABP2設(shè)備//RCC_APB1PeriphClockCmd(ABP2設(shè)備1 | ABP2設(shè)備2 |, ENABLE); //啟動ABP1設(shè)備}6、 閱讀exti:外部設(shè)備中斷函數(shù)我的理解——外部設(shè)備通過引腳給出的硬件中斷,也可以產(chǎn)生軟件中斷,19個(gè)上升、下降或都觸發(fā)。EXTI0~EXTI15連接到管腳,EXTI線16連接到PVD(VDD監(jiān)視),EXTI線17連接到RTC(鬧鐘),EXTI線18連接到USB(喚醒)。基礎(chǔ)應(yīng)用1,設(shè)定外部中斷初始化函數(shù)。按需求,不是必須代碼。用法: void EXTI_Configuration(void){EXTI_InitTypeDef EXTI_InitStructure; //外部設(shè)備中斷恢復(fù)默認(rèn)參數(shù)EXTI_InitStructure.EXTI_Line = 通道1|通道2; //設(shè)定所需產(chǎn)生外部中斷的通道,一共19個(gè)。EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //產(chǎn)生中斷EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //上升下降沿都觸發(fā) EXTI_InitStructure.EXTI_LineCmd = ENABLE; //啟動中斷的接收 EXTI_Init(&EXTI_InitStructure); //外部設(shè)備中斷啟動}7、 閱讀dma:通過總線而越過CPU讀取外設(shè)數(shù)據(jù)我的理解——通過DMA應(yīng)用可以加速單片機(jī)外設(shè)、存儲器之間的數(shù)據(jù)傳輸,并在傳輸期間不影響CPU進(jìn)行其他事情。這對于入門開發(fā)基本功能來說沒有太大必要,這個(gè)內(nèi)容先行跳過。8、 閱讀systic:系統(tǒng)定時(shí)器我的理解——可以輸出和利用系統(tǒng)時(shí)鐘的計(jì)數(shù)、狀態(tài)。基礎(chǔ)應(yīng)用1,精確計(jì)時(shí)的延時(shí)子函數(shù)。推薦使用的代碼。用法:static vu32 TimingDelay; //全局變量聲明void SysTick_Config(void) //systick初始化函數(shù){SysTick_CounterCmd(SysTick_Counter_Disable); //停止系統(tǒng)定時(shí)器SysTick_ITConfig(DISABLE); //停止systick中斷SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //systick使用HCLK作為時(shí)鐘源,頻率值除以8。SysTick_SetReload(9000); //重置時(shí)間1毫秒(以72MHz為基礎(chǔ)計(jì)算)SysTick_ITConfig(ENABLE); //開啟systic中斷}void Delay (u32 nTime) //延遲一毫秒的函數(shù){SysTick_CounterCmd(SysTick_Counter_Enable); //systic開始計(jì)時(shí)TimingDelay = nTime; //計(jì)時(shí)長度賦值給遞減變量while(TimingDelay != 0); //檢測是否計(jì)時(shí)完成SysTick_CounterCmd(SysTick_Counter_Disable); //關(guān)閉計(jì)數(shù)器SysTick_CounterCmd(SysTick_Counter_Clear); //清除計(jì)數(shù)值}void TimingDelay_Decrement(void) //遞減變量函數(shù),函數(shù)名由“stm32f10x_it.c”中的中斷響應(yīng)函數(shù)定義好了。{if (TimingDelay != 0x00) //檢測計(jì)數(shù)變量是否達(dá)到0{ TimingDelay--; //計(jì)數(shù)變量遞減}}注:建議熟練后使用,所涉及知識和設(shè)備太多,新手出錯的可能性比較大。新手可用簡化的延時(shí)函數(shù)代替:void Delay(vu32 nCount) //簡單延時(shí)函數(shù){for(; nCount != 0; nCount--); //循環(huán)變量遞減計(jì)數(shù)}當(dāng)延時(shí)較長,又不需要精確計(jì)時(shí)的時(shí)候可以使用嵌套循環(huán):void Delay(vu32 nCount) //簡單的長時(shí)間延時(shí)函數(shù){int i; //聲明內(nèi)部遞減變量for(; nCount != 0; nCount--) //遞減變量計(jì)數(shù){for (i=0; i<0xffff; i++)} //內(nèi)部循環(huán)遞減變量計(jì)數(shù)}9、 閱讀gpio:I/O設(shè)置函數(shù)我的理解——所有輸入輸出管腳模式設(shè)置,可以是上下拉、浮空、開漏、模擬、推挽模式,頻率特性為2M,10M,50M。也可以向該管腳直接寫入數(shù)據(jù)和讀取數(shù)據(jù)。基礎(chǔ)應(yīng)用1,gpio初始化函數(shù)。所有程序必須。用法:void GPIO_Configuration(void){GPIO_InitTypeDef GPIO_InitStructure; //GPIO狀態(tài)恢復(fù)默認(rèn)參數(shù)GPIO_InitStructure.GPIO_Pin = GPIO_Pin_標(biāo)號 | GPIO_Pin_標(biāo)號 ; //管腳位置定義,標(biāo)號可以是NONE、ALL、0至15。GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;//輸出速度2MHzGPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模擬輸入模式GPIO_Init(GPIOC, &GPIO_InitStructure); //C組GPIO初始化//注:以上四行代碼為一組,每組GPIO屬性必須相同,默認(rèn)的GPIO參數(shù)為:ALL,2MHz,FLATING。如果其中任意一行與前一組相應(yīng)設(shè)置相同,那么那一行可以省略,由此推論如果前面已經(jīng)將此行參數(shù)設(shè)定為默認(rèn)參數(shù)(包括使用GPIO_InitTypeDef GPIO_InitStructure代碼),本組應(yīng)用也是默認(rèn)參數(shù)的話,那么也可以省略。以下重復(fù)這個(gè)過程直到所有應(yīng)用的管腳全部被定義完畢。……}基礎(chǔ)應(yīng)用2,向管腳寫入0或1用法:GPIO_WriteBit(GPIOB, GPIO_Pin_2, (BitAction)0x01); //寫入1基礎(chǔ)應(yīng)用3,從管腳讀入0或1用法:GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6)STM32筆記之七:讓它跑起來,基本硬件功能的建立0、 實(shí)驗(yàn)之前的準(zhǔn)備a) 接通串口轉(zhuǎn)接器b) 下載IO與串口的原廠程序,編譯通過保證調(diào)試所需硬件正常。1、 flash,lib,nvic,rcc和GPIO,基礎(chǔ)程序庫編寫a) 這幾個(gè)庫函數(shù)中有一些函數(shù)是關(guān)于芯片的初始化的,每個(gè)程序中必用。為保障程序品質(zhì),初學(xué)階段要求嚴(yán)格遵守官方習(xí)慣。注意,官方程序庫例程中有個(gè)platform_config.h文件,是專門用來指定同類外設(shè)中第幾號外設(shè)被使用,就是說在main.c里面所有外設(shè)序號用x代替,比如USARTx,程序會到這個(gè)頭文件中去查找到底是用那些外設(shè),初學(xué)的時(shí)候參考例程別被這個(gè)所迷惑住。b) 全部必用代碼取自庫函數(shù)所帶例程,并增加逐句注釋。c) 習(xí)慣順序——Lib(debug),RCC(包括Flash優(yōu)化),NVIC,GPIOd) 必用模塊初始化函數(shù)的定義:void RCC_Configuration(void); //定義時(shí)鐘初始化函數(shù)void GPIO_Configuration(void); //定義管腳初始化函數(shù)void NVIC_Configuration(void); //定義中斷管理初始化函數(shù)void Delay(vu32 nCount); //定義延遲函數(shù)e) Main中的初始化函數(shù)調(diào)用:RCC_Configuration(); //時(shí)鐘初始化函數(shù)調(diào)用NVIC_Configuration(); //中斷初始化函數(shù)調(diào)用GPIO_Configuration(); //管腳初始化函數(shù)調(diào)用f) Lib注意事項(xiàng):屬于Lib的Debug函數(shù)的調(diào)用,應(yīng)該放在main函數(shù)最開始,不要改變其位置。g) RCC注意事項(xiàng):Flash優(yōu)化處理可以不做,但是兩句也不難也不用改參數(shù)……根據(jù)需要開啟設(shè)備時(shí)鐘可以節(jié)省電能時(shí)鐘頻率需要根據(jù)實(shí)際情況設(shè)置參數(shù)h) NVIC注意事項(xiàng)注意理解占先優(yōu)先級和響應(yīng)優(yōu)先級的分組的概念i) GPIO注意事項(xiàng)注意以后的過程中收集不同管腳應(yīng)用對應(yīng)的頻率和模式的設(shè)置。作為高低電平的I/O,所需設(shè)置:RCC初始化里面打開RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA);GPIO里面管腳設(shè)定:IO輸出(50MHz,Out_PP);IO輸入(50MHz,IPU);j) GPIO應(yīng)用GPIO_WriteBit(GPIOB, GPIO_Pin_2, Bit_RESET);//重置GPIO_WriteBit(GPIOB, GPIO_Pin_2, (BitAction)0x01);//寫入1GPIO_WriteBit(GPIOB, GPIO_Pin_2, (BitAction)0x00);//寫入0GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6) ;//讀入IOk) 簡單Delay函數(shù)void Delay(vu32 nCount)//簡單延時(shí)函數(shù){for(; nCount != 0; nCount--);}實(shí)驗(yàn)步驟:RCC初始化函數(shù)里添加:RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB , ENABLE);不用其他中斷,NVIC初始化函數(shù)不用改GPIO初始化代碼://IO輸入,GPIOB的2、10、11腳輸出GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 ;//管腳號GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //輸出速度GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //輸入輸出模式GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化簡單的延遲函數(shù):void Delay(vu32 nCount) //簡單延時(shí)函數(shù){ for (; nCount != 0; nCount--);} //循環(huán)計(jì)數(shù)延時(shí)完成之后再在main.c的while里面寫一段:GPIO_WriteBit(GPIOB, GPIO_Pin_2, (BitAction)0x01);//寫入1Delay(0xffff);GPIO_WriteBit(GPIOB, GPIO_Pin_2, (BitAction)0x00);//寫入0Delay(0xffff);就可以看到連接在PB2腳上的LED閃爍了,單片機(jī)就跑起來了。STM32筆記之八:來跟PC打個(gè)招呼,基本串口通訊a) 目的:在基礎(chǔ)實(shí)驗(yàn)成功的基礎(chǔ)上,對串口的調(diào)試方法進(jìn)行實(shí)踐。硬件代碼順利完成之后,對日后調(diào)試需要用到的printf重定義進(jìn)行調(diào)試,固定在自己的庫函數(shù)中。b) 初始化函數(shù)定義:void USART_Configuration(void); //定義串口初始化函數(shù)c) 初始化函數(shù)調(diào)用:void UART_Configuration(void); //串口初始化函數(shù)調(diào)用初始化代碼:void USART_Configuration(void) //串口初始化函數(shù){//串口參數(shù)初始化 USART_InitTypeDef USART_InitStructure; //串口設(shè)置恢復(fù)默認(rèn)參數(shù)//初始化參數(shù)設(shè)置USART_InitStructure.USART_BaudRate = 9600; //波特率9600USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字長8位USART_InitStructure.USART_StopBits = USART_StopBits_1; //1位停止字節(jié)USART_InitStructure.USART_Parity = USART_Parity_No; //無奇偶校驗(yàn)USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//無流控制USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//打開Rx接收和Tx發(fā)送功能USART_Init(USART1, &USART_InitStructure); //初始化USART_Cmd(USART1, ENABLE); //啟動串口}RCC中打開相應(yīng)串口RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 , ENABLE);GPIO里面設(shè)定相應(yīng)串口管腳模式//串口1的管腳初始化 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //管腳9GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復(fù)用推挽輸出GPIO_Init(GPIOA, &GPIO_InitStructure); //TX初始化GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //管腳10GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空輸入GPIO_Init(GPIOA, &GPIO_InitStructure); //RX初始化d) 簡單應(yīng)用:發(fā)送一位字符USART_SendData(USART1, 數(shù)據(jù)); //發(fā)送一位數(shù)據(jù)while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET){} //等待發(fā)送完畢接收一位字符while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET){} //等待接收完畢變量= (USART_ReceiveData(USART1)); //接受一個(gè)字節(jié)發(fā)送一個(gè)字符串先定義字符串:char rx_data[250];然后在需要發(fā)送的地方添加如下代碼int i; //定義循環(huán)變量while(rx_data!='\0') //循環(huán)逐字輸出,到結(jié)束字'\0'{USART_SendData(USART1, rx_data); //發(fā)送字符while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET){} //等待字符發(fā)送完畢i++;} e) USART注意事項(xiàng):發(fā)動和接受都需要配合標(biāo)志等待。只能對一個(gè)字節(jié)操作,對字符串等大量數(shù)據(jù)操作需要寫函數(shù)使用串口所需設(shè)置:RCC初始化里面打開RCC_APB2PeriphClockCmd(RCC_APB2Periph_USARTx);GPIO里面管腳設(shè)定:串口RX(50Hz,IN_FLOATING);串口TX(50Hz,AF_PP); f) printf函數(shù)重定義(不必理解,調(diào)試通過以備后用)(1) 需要c標(biāo)準(zhǔn)函數(shù):#include "stdio.h"(2) 粘貼函數(shù)定義代碼#define PUTCHAR_PROTOTYPE int __io_putchar(int ch) //定義為putchar應(yīng)用(3) RCC中打開相應(yīng)串口(4) GPIO里面設(shè)定相應(yīng)串口管腳模式(6) 增加為putchar函數(shù)。int putchar(int c) //putchar函數(shù){if (c == '\n'){putchar('\r');} //將printf的\n變成\rUSART_SendData(USART1, c); //發(fā)送字符while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET){} //等待發(fā)送結(jié)束return c; //返回值}(8) 通過,試驗(yàn)成功。printf使用變量輸出:%c字符,%d整數(shù),%f浮點(diǎn)數(shù),%s字符串,/n或/r為換行。注意:只能用于main.c中。3、 NVIC串口中斷的應(yīng)用a) 目的:利用前面調(diào)通的硬件基礎(chǔ),和幾個(gè)函數(shù)的代碼,進(jìn)行串口的中斷輸入練習(xí)。因?yàn)樵趯?shí)際應(yīng)用中,不使用中斷進(jìn)行的輸入是效率非常低的,這種用法很少見,大部分串口的輸入都離不開中斷。b) 初始化函數(shù)定義及函數(shù)調(diào)用:不用添加和調(diào)用初始化函數(shù),在指定調(diào)試地址的時(shí)候已經(jīng)調(diào)用過,在那個(gè)NVIC_Configuration里面添加相應(yīng)開中斷代碼就行了。c) 過程:i. 在串口初始化中USART_Cmd之前加入中斷設(shè)置:USART_ITConfig(USART1, USART_IT_TXE, ENABLE);//TXE發(fā)送中斷,TC傳輸完成中斷,RXNE接收中斷,PE奇偶錯誤中斷,可以是多個(gè)。ii. RCC、GPIO里面打開串口相應(yīng)的基本時(shí)鐘、管腳設(shè)置iii. NVIC里面加入串口中斷打開代碼:NVIC_InitTypeDef NVIC_InitStructure;//中斷默認(rèn)參數(shù)NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQChannel;//通道設(shè)置為串口1中斷NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //中斷占先等級0NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //中斷響應(yīng)優(yōu)先級0NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //打開中斷NVIC_Init(&NVIC_InitStructure); //初始化iv. 在stm32f10x_it.c文件中找到void USART1_IRQHandler函數(shù),在其中添入執(zhí)行代碼。一般最少三個(gè)步驟:先使用if語句判斷是發(fā)生那個(gè)中斷,然后清除中斷標(biāo)志位,最后給字符串賦值,或做其他事情。void USART1_IRQHandler(void) //串口1中斷{char RX_dat; //定義字符變量if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //判斷發(fā)生接收中斷{USART_ClearITPendingBit(USART1, USART_IT_RXNE); //清除中斷標(biāo)志GPIO_WriteBit(GPIOB, GPIO_Pin_10, (BitAction)0x01); //開始傳輸RX_dat=USART_ReceiveData(USART1) & 0x7F; //接收數(shù)據(jù),整理除去前兩位USART_SendData(USART1, RX_dat); //發(fā)送數(shù)據(jù)while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET){}//等待發(fā)送結(jié)束}}d) 中斷注意事項(xiàng):可以隨時(shí)在程序中使用USART_ITConfig(USART1, USART_IT_TXE, DISABLE);來關(guān)閉中斷響應(yīng)。NVIC_InitTypeDef NVIC_InitStructure定義一定要加在NVIC初始化模塊的第一句。全局變量與函數(shù)的定義:在任意.c文件中定義的變量或函數(shù),在其它.c文件中使用extern+定義代碼再次定義就可以直接調(diào)用了。STM32筆記之九:打斷它來為我辦事,EXIT (外部I/O中斷)應(yīng)用a) 目的:跟串口輸入類似,不使用中斷進(jìn)行的IO輸入效率也很低,而且可以通過EXTI插入按鈕事件,本節(jié)聯(lián)系EXTI中斷。b) 初始化函數(shù)定義:void EXTI_Configuration(void); //定義IO中斷初始化函數(shù)c) 初始化函數(shù)調(diào)用:EXTI_Configuration();//IO中斷初始化函數(shù)調(diào)用簡單應(yīng)用:d) 初始化函數(shù):void EXTI_Configuration(void){ EXTI_InitTypeDef EXTI_InitStructure; //EXTI初始化結(jié)構(gòu)定義EXTI_ClearITPendingBit(EXTI_LINE_KEY_BUTTON);//清除中斷標(biāo)志GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource3);//管腳選擇GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource4);GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource5);GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource6);EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//事件選擇EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//觸發(fā)模式EXTI_InitStructure.EXTI_Line = EXTI_Line3 | EXTI_Line4; //線路選擇EXTI_InitStructure.EXTI_LineCmd = ENABLE;//啟動中斷EXTI_Init(&EXTI_InitStructure);//初始化}e) RCC初始化函數(shù)中開啟I/O時(shí)鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);GPIO初始化函數(shù)中定義輸入I/O管腳。//IO輸入,GPIOA的4腳輸入GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉輸入GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化f) 在NVIC的初始化函數(shù)里面增加以下代碼打開相關(guān)中斷:NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQChannel; //通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//占先級NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //響應(yīng)級NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //啟動NVIC_Init(&NVIC_InitStructure); //初始化g) 在stm32f10x_it.c文件中找到void USART1_IRQHandler函數(shù),在其中添入執(zhí)行代碼。一般最少三個(gè)步驟:先使用if語句判斷是發(fā)生那個(gè)中斷,然后清除中斷標(biāo)志位,最后給字符串賦值,或做其他事情。if(EXTI_GetITStatus(EXTI_Line3) != RESET) //判斷中斷發(fā)生來源{ EXTI_ClearITPendingBit(EXTI_Line3); //清除中斷標(biāo)志USART_SendData(USART1, 0x41); //發(fā)送字符“a”GPIO_WriteBit(GPIOB, GPIO_Pin_2, (BitAction)(1-GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_2)));//LED發(fā)生明暗交替}h) 中斷注意事項(xiàng):中斷發(fā)生后必須清除中斷位,否則會出現(xiàn)死循環(huán)不斷發(fā)生這個(gè)中斷。然后需要對中斷類型進(jìn)行判斷再執(zhí)行代碼。使用EXTI的I/O中斷,在完成RCC與GPIO硬件設(shè)置之后需要做三件事:初始化EXTI、NVIC開中斷、編寫中斷執(zhí)行代碼。STM32筆記之十:工作工作,PWM輸出a) 目的:基礎(chǔ)PWM輸出,以及中斷配合應(yīng)用。輸出選用PB1,配置為TIM3_CH4,是目標(biāo)板的LED6控制腳。b) 對于簡單的PWM輸出應(yīng)用,暫時(shí)無需考慮TIM1的高級功能之區(qū)別。c) 初始化函數(shù)定義:void TIM_Configuration(void); //定義TIM初始化函數(shù)d) 初始化函數(shù)調(diào)用:TIM_Configuration(); //TIM初始化函數(shù)調(diào)用e) 初始化函數(shù),不同于前面模塊,TIM的初始化分為兩部分——基本初始化和通道初始化:void TIM_Configuration(void)//TIM初始化函數(shù){ TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;//定時(shí)器初始化結(jié)構(gòu)TIM_OCInitTypeDef TIM_OCInitStructure;//通道輸出初始化結(jié)構(gòu)//TIM3初始化TIM_TimeBaseStructure.TIM_Period = 0xFFFF; //周期0~FFFFTIM_TimeBaseStructure.TIM_Prescaler = 5; //時(shí)鐘分頻TIM_TimeBaseStructure.TIM_ClockDivision = 0; //時(shí)鐘分割TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//模式TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //基本初始化TIM_ITConfig(TIM3, TIM_IT_CC4, ENABLE);//打開中斷,中斷需要這行代碼//TIM3通道初始化TIM_OCStructInit(& TIM_OCInitStructure); //默認(rèn)參數(shù)TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //工作狀態(tài)TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //設(shè)定為輸出,需要PWM輸出才需要這行代碼TIM_OCInitStructure.TIM_Pulse = 0x2000; //占空長度TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //高電平TIM_OC4Init(TIM3, &TIM_OCInitStructure); //通道初始化TIM_Cmd(TIM3, ENABLE); //啟動TIM3}f) RCC初始化函數(shù)中加入TIM時(shí)鐘開啟:RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM3, ENABLE);g) GPIO里面將輸入和輸出管腳模式進(jìn)行設(shè)置。信號:AF_PP,50MHz。h) 使用中斷的話在NVIC里添加如下代碼://打開TIM2中斷NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQChannel; //通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;//占先級NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //響應(yīng)級NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //啟動NVIC_Init(&NVIC_InitStructure); //初始化中斷代碼:void TIM2_IRQHandler(void){if (TIM_GetITStatus(TIM2, TIM_IT_CC4) != RESET) //判斷中斷來源{TIM_ClearITPendingBit(TIM2, TIM_IT_CC4); //清除中斷標(biāo)志GPIO_WriteBit(GPIOB, GPIO_Pin_11, (BitAction)(1-GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_11)));//變換LED色彩IC4value = TIM_GetCapture4(TIM2); //獲取捕捉數(shù)值} }i) 簡單應(yīng)用://改變占空比TIM_SetCompare4(TIM3, 變量);j) 注意事項(xiàng):管腳的IO輸出模式是根據(jù)應(yīng)用來定,比如如果用PWM輸出驅(qū)動LED則應(yīng)該將相應(yīng)管腳設(shè)為AF_PP,否則單片機(jī)沒有輸出我的測試程序可以發(fā)出不斷循環(huán)三種波長并捕獲,對比結(jié)果如下:捕捉的穩(wěn)定性很好,也就是說,同樣的方波捕捉到數(shù)值相差在一兩個(gè)數(shù)值。捕捉的精度跟你設(shè)置的濾波器長度有關(guān),在這里TIM_ICInitStructure.TIM_ICFilter = 0x4; //濾波設(shè)置,經(jīng)歷幾個(gè)周期跳變認(rèn)定波形穩(wěn)定0x0~0xF這個(gè)越長就會捕捉數(shù)值越小,但是偏差幾十個(gè)數(shù)值,下面是0、4、16個(gè)周期濾波的比較,out是輸出的數(shù)值,in是捕捉到的。現(xiàn)在有兩個(gè)疑問:1、在TIM2的捕捉輸入通道初始化里面這句TIM_SelectInputTrigger(TIM2, TIM_TS_TI2FP2); //選擇時(shí)鐘觸發(fā)源按照硬件框圖,4通道應(yīng)該對應(yīng)TI4FP4。可是實(shí)際使用TI1FP1,TI2FP2都行,其他均編譯錯誤未注冊。這是為什么?2、關(guān)閉調(diào)試器和IAR程序,直接供電跑出來的結(jié)果第一個(gè)周期很正常,當(dāng)輸出脈寬第二次循環(huán)變小后捕捉的數(shù)值就差的遠(yuǎn)了。不知道是為什么STM32筆記之十二:時(shí)鐘不息工作不止,systic時(shí)鐘應(yīng)用a) 目的:使用系統(tǒng)時(shí)鐘來進(jìn)行兩項(xiàng)實(shí)驗(yàn)——周期執(zhí)行代碼與精確定時(shí)延遲。b) 初始化函數(shù)定義:void SysTick_Configuration(void);c) 初始化函數(shù)調(diào)用:SysTick_Configuration();d) 初始化函數(shù):void SysTick_Configuration(void){SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);//時(shí)鐘除8SysTick_SetReload(250000); //計(jì)數(shù)周期長度SysTick_CounterCmd(SysTick_Counter_Enable); //啟動計(jì)時(shí)器SysTick_ITConfig(ENABLE); //打開中斷}e) 在NVIC的初始化函數(shù)里面增加以下代碼打開相關(guān)中斷:NVIC_SystemHandlerPriorityConfig(SystemHandler_SysTick, 1, 0);//中斷等級設(shè)置,一般設(shè)置的高一些會少受其他影響f) 在stm32f10x_it.c文件中找到void SysTickHandler 函數(shù)void SysTickHandler(void){執(zhí)行代碼}g) 簡單應(yīng)用:精確延遲函數(shù),因?yàn)閟ystic中斷往往被用來執(zhí)行周期循環(huán)代碼,所以一些例程中使用其中斷的啟動和禁止來編寫的精確延時(shí)函數(shù)實(shí)際上不實(shí)用,我自己編寫了精確計(jì)時(shí)函數(shù)反而代碼更精簡,思路更簡單。思路是調(diào)用后,變量清零,然后使用時(shí)鐘來的曾變量,不斷比較變量與延遲的數(shù)值,相等則退出函數(shù)。代碼和步驟如下:i. 定義通用變量:u16 Tic_Val=0; //變量用于精確計(jì)時(shí)ii. 在stm32f10x_it.c文件中相應(yīng)定義:extern u16 Tic_Val;//在本文件引用MAIN.c定義的精確計(jì)時(shí)變量iii. 定義函數(shù)名稱:void Tic_Delay(u16 Tic_Count);//精確延遲函數(shù)iv. 精確延時(shí)函數(shù):void Tic_Delay(u16 Tic_Count) //精確延時(shí)函數(shù){ Tic_Val=0; //變量清零while(Tic_Val != Tic_Count){printf("");}//計(jì)時(shí)}v. 在stm32f10x_it.c文件中void SysTickHandler 函數(shù)里面添加Tic_Val++;//變量遞增vi. 調(diào)用代碼:Tic_Delay(10); //精確延時(shí)vii. 疑問:如果去掉計(jì)時(shí)行那個(gè)沒用的printf("");函數(shù)將停止工作,這個(gè)現(xiàn)象很奇怪C語言功底問題。是的,那個(gè)“注意事項(xiàng)”最后的疑問的原因就是這個(gè)Tic_Val應(yīng)該改為vu16while(Tic_Val != Tic_Count){printf("");}//計(jì)時(shí)就可以改為:while(Tic_Val != Tic_Count); //檢查變量是否計(jì)數(shù)到位STM32筆記之十三:惡搞,兩只看門狗a) 目的:了解兩種看門狗(我叫它:系統(tǒng)運(yùn)行故障探測器和獨(dú)立系統(tǒng)故障探測器,新手往往被這個(gè)并不形象的象形名稱搞糊涂)之間的區(qū)別和基本用法。b) 相同:都是用來探測系統(tǒng)故障,通過編寫代碼定時(shí)發(fā)送故障清零信號(高手們都管這個(gè)代碼叫做“喂狗”),告訴它系統(tǒng)運(yùn)行正常。一旦系統(tǒng)故障,程序清零代碼(“喂狗”)無法執(zhí)行,其計(jì)數(shù)器就會計(jì)數(shù)不止,直到記到零并發(fā)生故障中斷(狗餓了開始叫喚),控制CPU重啟整個(gè)系統(tǒng)(不行啦,開始咬人了,快跑……)。c) 區(qū)別:獨(dú)立看門狗Iwdg——我的理解是獨(dú)立于系統(tǒng)之外,因?yàn)橛歇?dú)立時(shí)鐘,所以不受系統(tǒng)影響的系統(tǒng)故障探測器。(這條狗是借來的,見誰偷懶它都咬!)主要用于監(jiān)視硬件錯誤。窗口看門狗wwdg——我的理解是系統(tǒng)內(nèi)部的故障探測器,時(shí)鐘與系統(tǒng)相同。如果系統(tǒng)時(shí)鐘不走了,這個(gè)狗也就失去作用了。(這條狗是老板娘養(yǎng)的,老板不干活兒他不管!)主要用于監(jiān)視軟件錯誤。d) 初始化函數(shù)定義:鑒于兩只狗作用差不多,使用過程也差不多初始化函數(shù)栓一起了,用的時(shí)候根據(jù)情況刪減。void WDG_Configuration(void);e) 初始化函數(shù)調(diào)用:WDG_Configuration();f) 初始化函數(shù)void WDG_Configuration() //看門狗初始化{//軟件看門狗初始化WWDG_SetPrescaler(WWDG_Prescaler_8); //時(shí)鐘8分頻4ms// (PCLK1/4096)/8= 244 Hz (~4 ms)WWDG_SetWindowValue(65); //計(jì)數(shù)器數(shù)值WWDG_Enable(127); //啟動計(jì)數(shù)器,設(shè)置喂狗時(shí)間// WWDG timeout = ~4 ms * 64 = 262 msWWDG_ClearFlag(); //清除標(biāo)志位WWDG_EnableIT(); //啟動中斷//獨(dú)立看門狗初始化IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);//啟動寄存器讀寫IWDG_SetPrescaler(IWDG_Prescaler_32);//40K時(shí)鐘32分頻IWDG_SetReload(349); //計(jì)數(shù)器數(shù)值IWDG_ReloadCounter(); //重啟計(jì)數(shù)器IWDG_Enable(); //啟動看門狗}g) RCC初始化:只有軟件看門狗需要時(shí)鐘初始化,獨(dú)立看門狗有自己的時(shí)鐘不需要但是需要systic工作相關(guān)設(shè)置。RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);h) 獨(dú)立看門狗使用systic的中斷來喂狗,所以添加systic的中斷打開代碼就行了。軟件看門狗需要在NVIC打開中斷添加如下代碼:NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQChannel; //通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //占先中斷等級NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //響應(yīng)中斷優(yōu)先級NVIC_Init(&NVIC_InitStructure); //打開中斷i) 中斷程序,軟件看門狗在自己的中斷中喂狗,獨(dú)立看門狗需要使用systic的定時(shí)中斷來喂狗。以下兩個(gè)程序都在stm32f10x_it.c文件中。void WWDG_IRQHandler(void){WWDG_SetCounter(0x7F); //更新計(jì)數(shù)值WWDG_ClearFlag(); //清除標(biāo)志位}void SysTickHandler(void){ IWDG_ReloadCounter(); //重啟計(jì)數(shù)器(喂狗)}j) 注意事項(xiàng):i. 有狗平常沒事情可以不理,但是千萬別忘了喂它,否則死都不知道怎么死的!ii. 初始化程序的調(diào)用一定要在systic的初始化之后。iii. 獨(dú)立看門狗需要systic中斷來喂,但是systic做別的用處不能只做這件事,所以我寫了如下幾句代碼,可以不影響systic的其他應(yīng)用,其他systic周期代碼也可參考:第一步:在stm32f10x_it.c中定義變量int Tic_IWDG; //喂狗循環(huán)程序的頻率判斷變量第二步:將SysTickHandler中喂狗代碼改為下面:Tic_IWDG++; //變量遞增if(Tic_IWDG>=100) //每100個(gè)systic周期喂狗{ IWDG_ReloadCounter();//重啟計(jì)數(shù)器(喂狗)Tic_IWDG=0; //變量清零}
總結(jié)
以上是生活随笔為你收集整理的stm32中断优先级分组的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: STM32串口学习总结(经典)
- 下一篇: stm32中#ifndef __LED_