环境搭建: 1、安装 Keil uVision4 MDK 略 2、安装 J-Link 安装 Setup_JLinkARM_V4501.exe 驱动时,会弹出【SEGGER J-Link DLL Updater V4.501 】对话框, 不要选择 Keil 直接点击OK即可,因为Keil对支持M3内核SW接口采用了JL2CM3.dll 这个文件,该文 件的版本号是和该目录下Jlink驱动版本号配套的,不要擅自改变他们,否则不能使用。 建立工程: 1、在桌面上建立一个文件夹【MyStm32】文件夹 2、在【MyStm32】文件夹下建立【USER】、【FWlib】、【CMSIS】、【Output】、【Listing】文件夹。 【USER】:存放用户自定义的应用程序 【FWlib】:存放库文件 【CMSIS】:存放M3系列单片机通用的文件 【Output】:存放编译器编译后输出的文件 【Listing】:编译器编译过程中产生的文件 3、将STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\STM32F10x_StdPeriph_Driver 的【inc】跟【src】 这两个文件夹拷贝到【FWlib】。 【inc】、【src】片上外设驱动的源文件和头文件。 4、\STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Template 下的 main.c、stm32f10x_conf.h、stm32f10x_it.h、stm32f10x_it.c 、system_stm32f10x.c 拷贝到【USER】 stm32f10x_conf.h:配置文件 stm32f10x_it.h、stm32f10x_it.c:中断函数文件。 system_stm32f10x.c:ARM公司提供的符合CMSIS标准的库文件 5、STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup的 【arm】文件夹的拷贝到 MyStm32\CMSIS\startup。 这些都是用汇编编写的驱动文件,STM32F103ZE芯片是大容量Flash,应选择startup_stm32f10x_hd.s 6、STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\CoreSupport 的 core_cm3.c 和 core_cm3.h 也拷贝到【CMSIS】文件夹下。 7、STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x 的 stm32f10x.h、system_stm32f10x.c、system_stm32f10x.h 拷贝到【CMSIS】文件夹下。 8、用keil MDK 建立工程文件到【USER】文件夹下,工程名为【STM32-DEMO】 在该工程下建立四个组: 【STARTCODE】:存放启动代码 添加 startup_stm32f10x_hd.s 文件 【USER】:存放用户自定义的应用程序 添加main.c、stm32f10x_it.c 【FWlib】:存放库文件 按需添加src里面的驱动文件 【CMSIS】:存放M3系列单片机通用的文件 添加core_cm3.c、system_stm32f10x.c 配置MDK: 添加 USE_STDPERIPH_DRIVER 是为了屏蔽编译器的默认搜索路径,转而使用我们添加 到工程中的 ST 的库,添加 STM32F10X_HD 是因为我们用的芯片是大容量的,添加了 STM32F10X_HD 这个宏之后,库文件里面为大容量定义的寄存器我们就可以用了。 芯片是小或中容量的时候宏要换成STM32F10X_LD或者STM32F10X_MD。其实不管是什么容量的, 我们只要添加上 STM32F10X_HD 这个宏即可,当你用小或者中容量的芯 片时,那些为大容量定义的寄存器我不去访问就是了,反正也访问不了。 流水灯实验: 只用到 配置GPIO功能和配置时钟功能,所以在 stm32f10x_conf.h 只需要包含两个头文件即可: #include "stm32f10x_gpio.h" #include "stm32f10x_rcc.h" 流水灯流程: 1、开启指定GPIO的外设时钟 -> RCC_APB2PeriphClockCmd() 2、设置 GPIO_InitTypeDef 指定引脚、工作状态、输出频率 3、根据 调用GPIO_Init() 初始化IO -> GPIO_Init() 4、设置IO输出高低电平,实现控制LED灯的亮灭。 led.c: #include "led.h" void LED_GPIO_Config(void) { // 定义一个 GPIO_InitTypeDef 类型的结构体 GPIO_InitTypeDef GPIO_InitStructure; // 开启 GPIOC 的外设时钟 RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE); // 选择要控制的 GPIOC 引脚 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5; // 设置引脚模式为通用推挽输出 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 设置引脚速率为 50Mhz GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 调用库函数,初始化GPIOC GPIO_Init(GPIOC, &GPIO_InitStructure); // 设置GPIOC3、GPIOC4、GPIOC5 为高电平 GPIO_SetBits(GPIOC, GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5); } led.h: #ifndef __LED_H #define __LED_H #include "stm32f10x.h" #include "stm32f10x_rcc.h" #define ON 0 #define OFF 1 //带参宏,可以向联函数一样使用 #define LED1(a) if(a) \ GPIO_SetBits(GPIOC, GPIO_Pin_3);\ else \ GPIO_ResetBits(GPIOC, GPIO_Pin_3) #define LED2(a) if(a) \ GPIO_SetBits(GPIOC, GPIO_Pin_4);\ else \ GPIO_ResetBits(GPIOC, GPIO_Pin_4) #define LED3(a) if(a) \ GPIO_SetBits(GPIOC, GPIO_Pin_5);\ else \ GPIO_ResetBits(GPIOC, GPIO_Pin_5) void LED_GPIO_Config(void); #endif main.c #include "stm32f10x.h" #include "led.c" void Delay(__IO u32 nCount) { for(; nCount !=0; nCount--); } int main(void) { LED_GPIO_Config(); while (1) { LED1(ON); Delay(0x0FFFEF); LED1(OFF); Delay(0x0FFFEF); } } ----------------------------------------------------------------------- 1. typedef enum 2. { 3. GPIO_Speed_10MHz = 1, //枚举常量,值为 1,代表输出速率最高为 10MHz 4. GPIO_Speed_2MHz, //对不赋值的枚举变量,自动加 1,此常量值为 2 5. GPIO_Speed_50MHz //常量值为 3 6. }GPIOSpeed_TypeDef 1. typedef enum 2. {GPIO_Mode_AIN = 0x0, //模拟输入模式 3. GPIO_Mode_IN_FLOATING = 0x04, //浮空输入模式 4. GPIO_Mode_IPD = 0x28, //下拉输入模式 5. GPIO_Mode_IPU = 0x48, //上拉输入模式 6. GPIO_Mode_Out_OD = 0x14, //开漏输出模式 7. GPIO_Mode_Out_PP = 0x10, //通用推挽输出模式 8. GPIO_Mode_AF_OD = 0x1C, //复用功能开漏输出 9. GPIO_Mode_AF_PP = 0x18 //复用功能推挽输出 10. }GPIOMode_TypeDef; 1. typedef struct 2. { 3. uint16_t GPIO_Pin; /*指定将要进行配置的 GPIO 引脚*/ 4. GPIOSpeed_TypeDef GPIO_Speed; /*指定 GPIO 引脚可输出的最高频率*/ 5. GPIOMode_TypeDef GPIO_Mode; /*指定 GPIO 引脚将要配置成的工作状态*/ 6. }GPIO_InitTypeDef; 实例: 31. /*选择要控制的 GPIOC 引脚*/ 32. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5; 33. 34. /*设置引脚模式为通用推挽输出*/ 35. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 36. 37. /*设置引脚速率为 50MHz */ 38. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; ----------------------------------------------------------------------- GPIO控制: void GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_InitStruct); 功能:根据 GPIOx 初始化GPIO 参数1:允许指为 GPIOA、GPIOB、GPIOC...GPIOG 参数2:GPIO_InitTypeDef 类型的指针,包含了指定引脚、输出工作状态和频率 实例: 40. /*调用库函数,初始化 GPIOC*/ 41. GPIO_Init(GPIOC, &GPIO_InitStructure); void GPIO_SetBits ( GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin) 功能:设置GPIO引脚输出高电平 参数1:允许指为 GPIOA、GPIOB、GPIOC...GPIOG 参数2:要控制的引脚号 Pin0~Pin15 void GPIO_ResetBits ( GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin) 功能:设置GPIO引脚输出低电平 参数1:允许指为 GPIOA、GPIOB、GPIOC...GPIOG 参数2:要控制的引脚号 Pin0~Pin15 ----------------------------------------------------------------------- 外设时钟控制: void RCC_APB2PeriphResetCmd ( uint32_t RCC_APB2Periph, FunctionalState NewState) 功能:开启或关闭的挂接在APB2总线上的外设时钟 参数1: RCC_APB2Periph_AFIO, RCC_APB2Periph_GPIOA, RCC_APB2Periph_GPIOB, RCC_APB2Periph_GPIOC, RCC_APB2Periph_GPIOD, RCC_APB2Periph_GPIOE, RCC_APB2Periph_GPIOF, RCC_APB2Periph_GPIOG, RCC_APB2Periph_ADC1, RCC_APB2Periph_ADC2, RCC_APB2Periph_TIM1, RCC_APB2Periph_SPI1, RCC_APB2Periph_TIM8, RCC_APB2Periph_USART1, RCC_APB2Periph_ADC3, RCC_APB2Periph_TIM15, RCC_APB2Periph_TIM16, RCC_APB2Periph_TIM17, RCC_APB2Periph_TIM9, RCC_APB2Periph_TIM10, RCC_APB2Periph_TIM11 参数2:使能外设时钟或关闭外设时钟 ENABLE or DISABLE void RCC_APB1PeriphClockCmd ( uint32_t RCC_APB1Periph, FunctionalState NewState) 功能:开启或关闭的挂接在APB2总线上的外设时钟 参数1: RCC_APB1Periph_TIM2, RCC_APB1Periph_TIM3, RCC_APB1Periph_TIM4, RCC_APB1Periph_TIM5, RCC_APB1Periph_TIM6, RCC_APB1Periph_TIM7, RCC_APB1Periph_WWDG, RCC_APB1Periph_SPI2, RCC_APB1Periph_SPI3, RCC_APB1Periph_USART2, RCC_APB1Periph_USART3, RCC_APB1Periph_USART4, RCC_APB1Periph_USART5, RCC_APB1Periph_I2C1, RCC_APB1Periph_I2C2, RCC_APB1Periph_USB, RCC_APB1Periph_CAN1, RCC_APB1Periph_BKP, RCC_APB1Periph_PWR, RCC_APB1Periph_DAC, RCC_APB1Periph_CEC, RCC_APB1Periph_TIM12, RCC_APB1Periph_TIM13, RCC_APB1Periph_TIM14 参数2:使能外设时钟或关闭外设时钟 ENABLE or DISABLE 【注意】:如果用到了I/O引脚的复用功能,则还要开启其复用功能的时钟。 如GPIOC的Pin4还可以作为ADC1的输入引脚,我们把它作为ADC1来使用, 那么除了要开启GPIOC时钟外,还需要开启ADC1的时钟。 例子: RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE); RCC_APB2PeriphClockCmd( RCC_APB2Periph_ADC1, ENABLE); ----------------------------------------------------------------------- ----------------------------------------------------------------------- 启动文件:startup_stm32f10x_hd.s 1. ;Reset_Handler 子程序开始 芯片被复位的时候会执行 2. Reset_Handler PROC 3. 4. ;输出子程序 Reset_Handler 到外部文件 5. EXPORT Reset_Handler [WEAK] 6. 7. ;从外部文件中引入 main 函数 8. IMPORT __main 9. 10. ;从外部文件引入 SystemInit 函数 11. IMPORT SystemInit 12. 13. ;把 SystemInit 函数调用地址加载到通用寄存器 r0 14. LDR R0, =SystemInit 15. 16. ;跳转到 r0 中保存的地址执行程序(调用 SystemInit 函数 用于设置系统时钟) 17. BLX R0 18. 19. ;把 main 函数调用地址加载到通用寄存器 r0 20. LDR R0, =__main 21. 22. ;跳转到 r0 中保存的地址执行程序(调用 main 函数) 23. BX R0 24. 25. ;Reset_Handler 子程序结束 26. ENDP 启动代码中,它会调用SystemInit(),SysteInit()会先将与配置时钟相关的寄存器复位为默认值。 然后它再调用SetSysClock()函数: 1. static void SetSysClock(void) 2. { 3. #ifdef SYSCLK_FREQ_HSE 4. SetSysClockToHSE(); 5. #elif defined SYSCLK_FREQ_24MHz 6. SetSysClockTo24(); 7. #elif defined SYSCLK_FREQ_36MHz 8. SetSysClockTo36(); 9. #elif defined SYSCLK_FREQ_48MHz 10. SetSysClockTo48(); 11. #elif defined SYSCLK_FREQ_56MHz 12. SetSysClockTo56(); 13. #elif defined SYSCLK_FREQ_72MHz 14. SetSysClockTo72(); // 配置相关寄存器 15. #endif 19. } SetSysClock()才是真正配置系统时钟函数,会根据宏来进行不同频率的配置。 由system_stm32f10x.c文件启用宏。 1. #if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL) 2. /* #define SYSCLK_FREQ_HSE HSE_VALUE */ 3. #define SYSCLK_FREQ_24MHz 24000000 4. #else 5. /* #define SYSCLK_FREQ_HSE HSE_VALUE */ 6. /* #define SYSCLK_FREQ_24MHz 24000000 */ 7. /* #define SYSCLK_FREQ_36MHz 36000000 */ 8. /* #define SYSCLK_FREQ_48MHz 48000000 */ 9. /* #define SYSCLK_FREQ_56MHz 56000000 */ 10. #define SYSCLK_FREQ_72MHz 72000000 11. #endif ----------------------------------------------------------------------- |
|