GPIO配置步驟:
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);//使能GPIOF時鍾
//GPIOF9,F10初始化設置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;//LED0和LED1對應IO口
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通輸出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOF, &GPIO_InitStructure);//初始化GPIOF9,F10
可以一次初始化一個IO組下的多個IO,前提是這些IO口的配置方式一樣。
按鍵配置:
使能按鍵對應IO口時鍾。調用函數:
RCC_AHB1PeriphClockCmd ();//參照GPIO配置過程
初始化IO模式:上拉/下拉輸入。調用函數:
GPIO_Init();//和GPIO配置過程一樣
掃描IO口電平(庫函數/寄存器/位操作)。
u8 KEY_Scan(u8 mode)
{
static u8 key_up=1;
if(mode==1) key_up=1;//支持連續按
if(key_up && KEY按下)
{
delay_ms(10);//延時,防抖
key_up=0;//標記這次key已經按下
if(KEY確實按下)
{
return KEY_VALUE;
}
}else if(KEY沒有按下) key_up=1;
return 沒有按下
}
端口復用配置過程:
①GPIO端口時鍾使能。
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
②復用外設時鍾使能。
比如你要將端口PA9,PA10復用為串口,所以要使能串口時鍾。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
③端口模式配置為復用功能。 GPIO_Init()函數。
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//復用功能
④配置GPIOx_AFRL或者GPIOx_AFRH寄存器,將IO連接
到所需的AFx。
/*PA9連接AF7,復用為USART1_TX */
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);
/* PA10連接AF7,復用為USART1_RX*/
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);
例子:
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA時鍾 ①
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1時鍾 ②
//USART1端口配置③
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9與GPIOA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//復用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽復用輸出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA9,PA10
//串口1對應引腳復用映射 ④
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //GPIOA9復用為USART1
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10復用為USART1
中斷優先級配置過程:
系統運行后先設置中斷優先級分組。調用函數:
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
整個系統執行過程中,只設置一次中斷分組。
針對每個中斷,設置對應的搶占優先級和響應優先級:
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);
如果需要掛起/解掛,查看中斷當前激活狀態,分別調用相關函數即可。
例子:
typedef struct
{
uint8_t NVIC_IRQChannel; //設置中斷通道
uint8_t NVIC_IRQChannelPreemptionPriority;//設置響應優先級
uint8_t NVIC_IRQChannelSubPriority; //設置搶占優先級
FunctionalState NVIC_IRQChannelCmd; //使能/使能
} NVIC_InitTypeDef;
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口1中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;// 搶占優先級為1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;// 子優先級位2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根據上面指定的參數初始化NVIC寄存器
串口配置:
① 串口時鍾使能:RCC_APBxPeriphClockCmd();
GPIO時鍾使能:RCC_AHB1PeriphClockCmd();
② 引腳復用映射:
GPIO_PinAFConfig();
③GPIO端口模式設置:GPIO_Init(); 模式設置為GPIO_Mode_AF
④串口參數初始化:USART_Init();
⑤開啟中斷並且初始化NVIC(如果需要開啟中斷才需要這個步驟)
NVIC_Init();
USART_ITConfig();
⑥使能串口:USART_Cmd();
⑦編寫中斷處理函數:USARTx_IRQHandler();
⑧串口數據收發:
void USART_SendData();//發送數據到串口,DR
uint16_t USART_ReceiveData();//接受數據,從DR讀取接受到的數據
⑨串口傳輸狀態獲取:
FlagStatus USART_GetFlagStatus();
void USART_ClearITPendingBit();
外部中斷配置:
使能SYSCFG時鍾:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
初始化IO口為輸入。
GPIO_Init();
設置IO口與中斷線的映射關系。
void SYSCFG_EXTILineConfig();
初始化線上中斷,設置觸發條件等。
EXTI_Init();
配置中斷分組(NVIC),並使能中斷。
NVIC_Init();
編寫中斷服務函數。
EXTIx_IRQHandler();
清除中斷標志位
EXTI_ClearITPendingBit();
EXTI_InitStructure.EXTI_Line=EXTI_Line2;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
獨立看門狗配置過程:
1.取消寄存器寫保護:
IWDG_WriteAccessCmd();
2.設置獨立看門狗的預分頻系數,確定時鍾:
IWDG_SetPrescaler();
3.設置看門狗重裝載值,確定溢出時間:
IWDG_SetReload();
4.使能看門狗
IWDG_Enable();
5.應用程序喂狗:
IWDG_ReloadCounter();
溢出時間計算:
Tout=((4×2^prer) ×rlr) /32 (M4) 注意單位統一
prep:預分頻系數 rlr:重裝載值
void IWDG_Init(u8 prer,u16 rlr)
{
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
IWDG_SetPrescaler(prer);
IWDG_SetReload(rlr);
IWDG_ReloadCounter();
IWDG_Enable();
}
主函數中設置中斷優先級分組,初始化IO;調用IWDG_Init(4,500); 在while中進行喂狗。
窗口看門狗配置:
1.使能看門狗時鍾:
RCC_APB1PeriphClockCmd();
2.設置分頻系數:
WWDG_SetPrescaler();
3.設置上窗口值:
WWDG_SetWindowValue();
4.開啟提前喚醒中斷並分組(可選):
WWDG_EnableIT();
NVIC_Init();
5.使能看門狗:
WWDG_Enable();
6.喂狗:
WWDG_SetCounter();
7.編寫中斷服務函數
WWDG_IRQHandler();
void WWDG_Init(u8 tr,u8 wr,u32 fprer)
{
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE); //使能窗口看門狗時鍾
WWDG_CNT=tr&WWDG_CNT; //初始化WWDG_CNT.
WWDG_SetPrescaler(fprer); //設置分頻值
WWDG_SetWindowValue(wr); //設置窗口值
// WWDG_SetCounter(WWDG_CNT);//設置計數值
WWDG_Enable(WWDG_CNT); //開啟看門狗
NVIC_InitStructure.NVIC_IRQChannel=WWDG_IRQn; //窗口看門狗中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x02; //搶占優先級為2
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x03; //子優先級為3
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; //使能窗口看門狗
NVIC_Init(&NVIC_InitStructure);
WWDG_ClearFlag();//清除提前喚醒中斷標志位
WWDG_EnableIT();//開啟提前喚醒中斷
}
//窗口看門狗中斷服務程序
void WWDG_IRQHandler(void)
{
WWDG_SetCounter(WWDG_CNT); //重設窗口看門狗值
WWDG_ClearFlag();//清除提前喚醒中斷標志位
LED1=!LED1;
}
定時器中斷配置:
1.能定時器時鍾。
RCC_APB1PeriphClockCmd();
2.初始化定時器,配置ARR,PSC。
TIM_TimeBaseInit();
3.開啟定時器中斷,配置NVIC。
NVIC_Init();
4.使能定時器。
TIM_Cmd();
5.編寫中斷服務函數。
TIMx_IRQHandler();
void TIM3_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); ///使能TIM3時鍾
TIM_TimeBaseInitStructure.TIM_Period = arr; //自動重裝載值
TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //定時器分頻
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上計數模式
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);//初始化TIM3
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); //允許定時器3更新中斷
TIM_Cmd(TIM3,ENABLE); //使能定時器3
NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn; //定時器3中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01; //搶占優先級1
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x03; //子優先級3
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
pwm輸出配置:
1.使能定時器14和相關IO口時鍾。
使能定時器14時鍾:RCC_APB1PeriphClockCmd();
使能GPIOF時鍾:RCC_AHB1PeriphClockCmd ();
2.初始化IO口為復用功能輸出。函數:GPIO_Init();
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //復用功能
3.GPIOF9復用映射到定時器14
GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14);
4.初始化定時器:ARR,PSC等:TIM_TimeBaseInit();
5.初始化輸出比較參數:TIM_OC1Init();
6.使能預裝載寄存器: TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable);
7.使能自動重裝載的預裝載寄存器允許位TIM_ARRPreloadConfig(TIM14,ENABLE);
8.使能定時器。
9.不斷改變比較值CCRx,達到不同的占空比效果:TIM_SetCompare1();
void TIM14_PWM_Init(u32 arr,u32 psc)
{
//此部分需手動修改IO口設置
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14,ENABLE); //TIM14時鍾使能
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); //使能PORTF時鍾
GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14); //GPIOF9復用為定時器14
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //GPIOF9
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //復用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度100MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽復用輸出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOF,&GPIO_InitStructure); //初始化PF9
TIM_TimeBaseStructure.TIM_Prescaler=psc; //定時器分頻
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上計數模式
TIM_TimeBaseStructure.TIM_Period=arr; //自動重裝載值
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM14,&TIM_TimeBaseStructure);//初始化定時器14
//初始化TIM14 Channel1 PWM模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //選擇定時器模式:TIM脈沖寬度調制模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比較輸出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //輸出極性:TIM輸出比較極性低
TIM_OC1Init(TIM14, &TIM_OCInitStructure); //根據T指定的參數初始化外設TIM1 4OC1
TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable); //使能TIM14在CCR1上的預裝載寄存器
TIM_ARRPreloadConfig(TIM14,ENABLE);//ARPE使能
TIM_Cmd(TIM14, ENABLE); //使能TIM14
}
輸入捕獲配置:
① 初始化定時器和通道對應IO的時鍾。
② 初始化IO口,模式為復用:GPIO_Init();
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
③設置引腳復用映射:
GPIO_PinAFConfig();
④初始化定時器ARR,PSC
TIM_TimeBaseInit();
⑤初始化輸入捕獲通道
TIM_ICInit();
⑥如果要開啟捕獲中斷,
TIM_ITConfig();
NVIC_Init();
⑦使能定時器:TIM_Cmd();
⑧編寫中斷服務函數:TIMx_IRQHandler();
void TIM5_CH1_Cap_Init(u32 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE); //TIM5時鍾使能
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //使能PORTA時鍾
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //GPIOA0
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//復用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度100MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽復用輸出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; //下拉
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA0
GPIO_PinAFConfig(GPIOA,GPIO_PinSource0,GPIO_AF_TIM5); //PA0復用位定時器5
TIM_TimeBaseStructure.TIM_Prescaler=psc; //定時器分頻
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上計數模式
TIM_TimeBaseStructure.TIM_Period=arr; //自動重裝載值
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM5,&TIM_TimeBaseStructure);
//初始化TIM5輸入捕獲參數
TIM5_ICInitStructure.TIM_Channel = TIM_Channel_1; //CC1S=01 選擇輸入端 IC1映射到TI1上
TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕獲
TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上
TIM5_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置輸入分頻,不分頻
TIM5_ICInitStructure.TIM_ICFilter = 0x00;//IC1F=0000 配置輸入濾波器 不濾波
TIM_ICInit(TIM5, &TIM5_ICInitStructure);
TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);//允許更新中斷 ,允許CC1IE捕獲中斷
TIM_Cmd(TIM5,ENABLE ); //使能定時器5
NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;//搶占優先級3
NVIC_InitStructure.NVIC_IRQChannelSubPriority =0; //子優先級3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根據指定的參數初始化VIC寄存器、
}