目錄
1、IO的幾種模式
2、 GPIO初始化(led)
3、 GPIO初始化(key)
4、主函數初始化
5、硬件延時函數
6、中斷EXTI及NVIC配置
7、通用定時器
8、USART的使用
工程文件夾示意圖:
軟件中建立文件夾所包含內容:
魔術棒配置:
1、IO的幾種模式:
/* 選擇IO接口工作方式: GPIO_Mode_AIN 模擬輸入 GPIO_Mode_IN_FLOATING 浮空輸入 GPIO_Mode_IPD 下拉輸入 用於按鍵,具體看電路圖 GPIO_Mode_IPU 上拉輸入 用於按鍵,具體看電路圖 GPIO_Mode_Out_PP 推挽輸出 用於LED GPIO_Mode_Out_OD 開漏輸出 GPIO_Mode_AF_PP 復用推挽輸出 GPIO_Mode_AF_OD 復用開漏輸出 */
2、 GPIO初始化(led)
需要建立led.c及led.h文件
Led.c內容:
#include "led.h" //LED燈的接口初始化,"void LED_Config(void);"需要在led.h中進行聲明 void LED_Config(void){ GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); //開啟總線時鍾 GPIO_InitStructure.GPIO_Pin =GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9; //選擇端口號(0~15或all) GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //選擇IO接口工作方式,使用推挽輸出模式,可輸出高低電平 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //設置IO接口速度(2/10/50MHz) GPIO_Init(GPIOC, &GPIO_InitStructure); }
Led.h內容:
#ifndef __LED_H #define __LED_H #include "stm32f10x.h"//包含庫頭文件,才可使用庫函數,如 GPIO_SetBits(GPIOC, GPIO_Pin_6); void LED_Config(void);//進行函數名的聲明 #endif
3、 GPIO初始化(key)
需要建立key.c及key.h文件
key.c內容:
#include "key.h" //KEY的接口初始化 void KEY_Config(void){ GPIO_InitTypeDef GPIO_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //開啟總線時鍾 GPIO_InitStruct.GPIO_Pin =GPIO_Pin_8|GPIO_Pin_9; //選擇端口號(0~15或all) GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; //選擇IO接口工作方式,上拉模式 // GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; //按鍵為輸入,不用設置IO接口速度 GPIO_Init(GPIOB, &GPIO_InitStruct); }
key.h內容:
#ifndef __KEY_H #define __KEY_H #include "stm32f10x.h" void KEY_Config(void);//進行函數名的聲明 #endif
4、主函數初始化:
#include "stm32f10x.h" #include "led.h" //包含頭文件 #include "key.h"//包含頭文件 int main(void){ uint32_t t=2;//定義變量必須在初始化前面 KEY_Config();//在此處進行初始化 LED_Config();//在此處進行初始化 while(1){ } }
5、硬件延時函數:
delay.c內容:
#include "delay.h" void delay_us ( unsigned int us) //微秒級延時函數,嘀嗒定時器為24位向下計數器 { SysTick -> VAL = 0; //設置計數器初值為0,一共32位,24位可用 SysTick -> LOAD = 9*us; //每計9個數才是1us,這里和TIM定時器計數有區別 SysTick -> CTRL = 0x01; //使能計數器,第0位為使能位,置1使能,置0失能 while((SysTick ->CTRL) != 0x10001); //向下產生溢出后,產生中斷標志,及判斷16位是否置1 SysTick -> CTRL =0; //產生溢出后,產生中斷標志的第16位被置1,此時再將第16位置0,以便下次計數 SysTick -> VAL =0; //設置計數器初值為0,一共32位,24位可用 } void delay_ms ( unsigned int ms) //毫秒級延時函數,嘀嗒定時器為24位向下計數器 { SysTick -> VAL = 0;//設置計數器初值為0,一共32位,24位可用 SysTick -> LOAD = 9000*ms;//這里計9000個數才是1ms,這里和TIM定時器計數有區別 SysTick -> CTRL = 0x01;//使能計數器,第0位為使能位,置1使能,置0失能 while((SysTick ->CTRL) != 0x10001);//向下產生溢出后,產生中斷標志,及判斷16位是否置1 SysTick -> CTRL =0;//產生溢出后,產生中斷標志的第16位被置1,此時再將第16位置0,以便下次計數 SysTick -> VAL =0;//設置計數器初值為0,一共32位,24位可用 }
delay.h內容:
#ifndef __DELAY_H #define __DELAY_H #include "stm32f10x.h" void delay_us(unsigned int us); void delay_ms(unsigned int ms); #endif
不用在main.c中初始化,只需要包含#include "delay.h"即可,就可以進行函數的調用:delay_ms(100);
6、中斷EXTI及NVIC配置:
exti.c內容:
#include "exti.h" //EXTI的接口初始化及NVIC配置 void EXTI_Config(void){ GPIO_InitTypeDef GPIO_InitStructure; //GPIO端口的初始化 EXTI_InitTypeDef EXTI_InitStructure; //EXTI配置 NVIC_InitTypeDef NVIC_InitStruct; //NVIC配置 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);//第一組 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //開啟GPIO端口時鍾 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //開啟GPIO端口復用時鍾 GPIO_InitStructure.GPIO_Pin =GPIO_Pin_8|GPIO_Pin_9; //選擇端口號(0~15或all) GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //選擇IO接口工作方式 ,上拉模式 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //設置IO接口速度(2/10/50MHz) GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource8); //將中斷線與引腳連接起來,GPIO_PortSourceGPIOB固件庫手冊有錯 GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource9); //將中斷線與引腳連接起來,GPIO_PortSourceGPIOB固件庫手冊有錯 EXTI_InitStructure.EXTI_Line = EXTI_Line8|EXTI_Line9; //對應中斷IO口的引腳,Pin_8,Pin_9 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //中斷觸發模式 EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿觸發方式 EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); NVIC_InitStruct.NVIC_IRQChannel = EXTI9_5_IRQn;//第5~9線通用 NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;//主優先級 NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;//從優先級 NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStruct); }
exti.h內容:
#ifndef __EXTI_H #define __EXTI_H #include "stm32f10x.h" #include "exti.h" void EXTI_Config(void); #endif
主函數main.c中需要包含頭文件:#include "exti.h" 並進行初始化:EXTI_Config();
中斷函數文件 "stm32f10x_it.c" 需要包含led.h key.h delay.h exti.h 才能實現相應的功能
stm32f10x_it.c 需要添加的內容:
#include "exti.h" #include "beep.h" #include "delay.h" #include "led.h" //按鍵產生中斷,進入此函數進行以下兩個if語句判斷 void EXTI9_5_IRQHandler (void)//固定函數名,不可自定義,否則無法進入中斷 { if((EXTI_GetITStatus(EXTI_Line8) == 1)|(EXTI_GetITStatus(EXTI_Line9) == 1)){ if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_8)==0){ delay_ms(20); BEEP_Warning();//蜂鳴器鳴叫功能 } if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_9)==0){ delay_ms(20); LM_Led(); //流水燈功能 } } EXTI_ClearITPendingBit(EXTI_Line8);//必須進行中斷掛起位的清除,否則無法進入下次中斷 EXTI_ClearITPendingBit(EXTI_Line9); }
7、通用定時器
timer.c包含內容:
#include "timer.h" static void TIMER3_NVIC_Config(void) { NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); // 設置中斷組為0 NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn ; // 設置中斷來源 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 設置主優先級為 0 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; // 設置搶占優先級為3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } static void TIMER3_Config(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);// 開啟定時器時鍾,即內部時鍾CK_INT=72M TIM_TimeBaseStructure.TIM_Period = 1000-1; // 計數的次數 ARR ;如果計1000次數,那么寫成1000-1,后面計算的時候會自動加1 //即1000次(1000us)溢出,產生中斷,此時在中斷函數中定義一個變量記錄中斷次數 TIM_TimeBaseStructure.TIM_Prescaler= 72-1;// 分頻因子 PSC ;如果分72,那么寫成72-1,后面計算的時候會自動加1 // 時鍾分頻因子 ,基本定時器沒有,不用管 // TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; // 計數器計數模式,基本定時器只能向上計數,沒有計數模式的設置 TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; // 重復計數器的值,基本定時器沒有,不用管 // TIM_TimeBaseStructure.TIM_RepetitionCounter=0; TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);// 初始化定時器 TIM_ClearFlag(TIM3, TIM_FLAG_Update);// 清除計數器中斷標志位 TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);// 開啟計數器中斷 TIM_Cmd(TIM3, ENABLE);// 使能計數器 } void TIMER3_Init(void){ TIMER3_NVIC_Config(); TIMER3_Config(); }
timer.h 包含內容:
#ifndef __TIMER_H #define __TIMER_H #include "stm32f10x.h" void TIMER3_Init(void); #endif
主函數main.c中進行初始化:TIMER3_Init();初始化后計數器將開始自動計時,不需要外部干預,計數完后將自動跳到 "stm32f10x_it.c" 中,執行完中斷函數后,自動返回主函數上次斷點繼續執行
執行相關的中斷程序:
//執行流水燈功能 void TIM3_IRQHandler(void) //固定函數名稱 { if ( TIM_GetITStatus( TIM3, TIM_IT_Update) != RESET ) //檢查指定的 TIM 中斷發生與否 { Countcycle++;//記錄中斷次數,uint16_t Countcycle就在stm32f10x_it.c開頭進行定義 switch(Countcycle){ case 1000 : GPIO_SetBits(GPIOC, GPIO_Pin_6); GPIO_ResetBits(GPIOC, GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9); break; case 2000 : GPIO_SetBits(GPIOC, GPIO_Pin_7); GPIO_ResetBits(GPIOC, GPIO_Pin_6|GPIO_Pin_8|GPIO_Pin_9); break; case 3000 : GPIO_SetBits(GPIOC, GPIO_Pin_8); GPIO_ResetBits(GPIOC, GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_9); break; case 4000 : GPIO_SetBits(GPIOC, GPIO_Pin_9); GPIO_ResetBits(GPIOC, GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8); Countcycle=0;break; } TIM_ClearITPendingBit(TIM3 , TIM_FLAG_Update); //清除 TIMx 的中斷待處理位 } }
8、USART的使用:
usart.c內容:
#include "usart.h" static void NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//嵌套向量中斷控制器組選擇 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;// 配置USART為中斷源 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;// 搶斷優先級 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //子優先級 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中斷 NVIC_Init(&NVIC_InitStructure);// 初始化配置NVIC } void USART_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);// 打開串口GPIO的時鍾 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);// 打開串口外設的時鍾 // 將USART Tx的GPIO配置為推挽復用模式 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//推挽復用 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // 將USART Rx的GPIO配置為浮空輸入模式 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); // 配置串口的工作參數 USART_InitStructure.USART_BaudRate = 115200;// 配置波特率 USART_InitStructure.USART_WordLength = USART_WordLength_8b;// 配置 針數據字長 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);// 完成串口的初始化配置 NVIC_Configuration();// 串口中斷優先級配置,上面已經配置,直接調用 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // 使能串口接收中斷 USART_Cmd(USART1, ENABLE);// 使能串口 } //重定向c庫函數printf到串口,重定向后可使用printf函數,使用該函數是,需要在魔術棒中的Target選項卡中勾選使用微庫或包含頭文件#include "stdio.h" int fputc(int ch, FILE *f)//用法:printf( "這是一個串口打印實驗\n" ); { USART_SendData(USART1, (uint8_t) ch);//發送一個字節數據到串口 while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); //等待發送完畢 return (ch); }
usart.h內容:
#ifndef __BSP_USART_H #define __BSP_USART_H #include "stm32f10x.h" #include <stdio.h> //在此處包含即可 void USART_Config(void); #endif
"stm32f10x_it.c"中需要包含頭文件 #include "usart.h" 和中斷服務函數:
//串口中斷服務函數 void USART1_IRQHandler(void)//固定函數名 { uint8_t ucTemp; if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET) { ucTemp = USART_ReceiveData(USART1);//接受到數據存放至變量ucTemp中 USART_SendData(USART1,ucTemp); //變量ucTemp中數據發出去 } }
主函數main.c中進行初始化:USART_Config(); 並包含頭文件 #include "usart.h"
主函數main.c內容:
#include "stm32f10x.h" #include "usart.h" #include "delay.h" int main(void) { USART_Config(); while (1) { delay_ms(1000); printf( "lin辰傍邊的風\n" ); } }