STM32F10*系列单片机开发
开发方式
常用于开发STM32的有三种方式:
直接操作寄存器
使用官方库函数
ST官方推出的HAL库
这三者区别在于:操作寄存器过于麻烦,库函数只适合某系列的STM32单片机(比如STM32F1的代码就不能直接移植到STM32F4上去),HAL库则适用于STM32全系列单片机。且目前库函数版本官方已经停止更新,大势所趋是使用HAL库。
不同芯片的开发
不同的STM32芯片可以共用同一份HAL库,但是并不意味着代码可以完全不改,不同的芯片引脚数、引脚用处可能不尽相同。比如STM32F103ZET6有144个引脚,STM32F103C8T6只有48个引脚。
在开发时,我们需要查看相应的数据手册和电路板的原理图。
以网上找到的STM32F103C8T6资料为例(方便后续查找):
可以看到虽然引脚数不同,但是对于同一引脚对应的主要功能和额外功能都是相同的。因此我们在将其他芯片的代码迁移过来时,需要额外关注使用的芯片是否具有该引脚,没有则需要寻找合适的引脚替代以实现想要的功能。此外我们还需要关注芯片的外设,以下图为例,正点原子的精英版STM32F1的LED灯的引脚为PB5和PE5,而STM32F103C8T6的LED灯引脚为PC13。
示例
下面以STM32F103C8T6实现红外遥控实验:
主要是根据正点原子提供的HAL库修改实现
代码
main函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| #include "sys.h" #include "delay.h" #include "led.h" #include "remote.h"
int main(void) { u8 key; HAL_Init(); Stm32_Clock_Init(RCC_PLL_MUL9); delay_init(72); LED_Init();
Remote_Init(); while(1) { key=Remote_Scan(); if(key) { HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET); } HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET); } }
|
红外接收源文件remote.c:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
| #include "remote.h" #include "delay.h" TIM_HandleTypeDef TIM4_Handler;
void Remote_Init(void) { TIM_IC_InitTypeDef TIM4_CH1Config; TIM4_Handler.Instance=TIM4; TIM4_Handler.Init.Prescaler=(72-1); TIM4_Handler.Init.CounterMode=TIM_COUNTERMODE_UP; TIM4_Handler.Init.Period=10000; TIM4_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1; HAL_TIM_IC_Init(&TIM4_Handler); TIM4_CH1Config.ICPolarity=TIM_ICPOLARITY_RISING; TIM4_CH1Config.ICSelection=TIM_ICSELECTION_DIRECTTI; TIM4_CH1Config.ICPrescaler=TIM_ICPSC_DIV1; TIM4_CH1Config.ICFilter=0x03; HAL_TIM_IC_ConfigChannel(&TIM4_Handler,&TIM4_CH1Config,TIM_CHANNEL_4); HAL_TIM_IC_Start_IT(&TIM4_Handler,TIM_CHANNEL_4); **HAL_TIM_ENABLE_IT(&TIM4_Handler,TIM_IT_UPDATE); }
void HAL_TIM_IC_MspInit(TIM_HandleTypeDef *htim) { GPIO_InitTypeDef GPIO_Initure; **HAL_RCC_TIM4_CLK_ENABLE(); **HAL_RCC_GPIOB_CLK_ENABLE(); GPIO_Initure.Pin=GPIO_PIN_9; GPIO_Initure.Mode=GPIO_MODE_AF_INPUT; GPIO_Initure.Pull=GPIO_PULLUP; GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOB,&GPIO_Initure);
HAL_NVIC_SetPriority(TIM4_IRQn,1,3); HAL_NVIC_EnableIRQ(TIM4_IRQn); }
u8 RmtSta=0; u16 Dval; u32 RmtRec=0; u8 RmtCnt=0;
void TIM4_IRQHandler(void) { HAL_TIM_IRQHandler(&TIM4_Handler); }
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim->Instance==TIM4) { if(RmtSta&0x80) { RmtSta&=~0X10; if((RmtSta&0X0F)==0X00)RmtSta|=1<<6; if((RmtSta&0X0F)<14)RmtSta++; else { RmtSta&=~(1<<7); RmtSta&=0XF0; } } } }
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if(htim->Instance==TIM4) { if(RDATA) { TIM_RESET_CAPTUREPOLARITY(&TIM4_Handler,TIM_CHANNEL_4); TIM_SET_CAPTUREPOLARITY(&TIM4_Handler,TIM_CHANNEL_4,TIM_ICPOLARITY_FALLING); **HAL_TIM_SET_COUNTER(&TIM4_Handler,0); RmtSta|=0X10; }else { Dval=HAL_TIM_ReadCapturedValue(&TIM4_Handler,TIM_CHANNEL_4); TIM_RESET_CAPTUREPOLARITY(&TIM4_Handler,TIM_CHANNEL_4); TIM_SET_CAPTUREPOLARITY(&TIM4_Handler,TIM_CHANNEL_4,TIM_ICPOLARITY_RISING); if(RmtSta&0X10) { if(RmtSta&0X80) { if(Dval>300&&Dval<800) { RmtRec<<=1; RmtRec|=0; }else if(Dval>1400&&Dval<1800) { RmtRec<<=1; RmtRec|=1; }else if(Dval>2200&&Dval<2600) { RmtCnt++; RmtSta&=0XF0; } }else if(Dval>4200&&Dval<4700) { RmtSta|=1<<7; RmtCnt=0; } } RmtSta&=~(1<<4); } } }
u8 Remote_Scan(void) { u8 sta=0; u8 t1,t2; if(RmtSta&(1<<6)) { t1=RmtRec>>24; t2=(RmtRec>>16)&0xff; if((t1==(u8)~t2)&&t1==REMOTE_ID) { t1=RmtRec>>8; t2=RmtRec; if(t1==(u8)~t2)sta=t1; } if((sta==0)||((RmtSta&0X80)==0)) { RmtSta&=~(1<<6); RmtCnt=0; } } return sta; }
|
红外接收头文件remote.h:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| #ifndef **REMOTE_H #define **REMOTE_H #include "sys.h"
#define RDATA PBin(9)
#define REMOTE_ID 0
extern u8 RmtCnt;
void Remote_Init(void); u8 Remote_Scan(void); #endif
|
LED灯led.c:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| #include "led.h"
void LED_Init(void) { GPIO_InitTypeDef GPIO_Initure;
**HAL_RCC_GPIOC_CLK_ENABLE();
GPIO_Initure.Pin=GPIO_PIN_13; GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; GPIO_Initure.Pull=GPIO_PULLUP; GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOC,&GPIO_Initure);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);
}
|
接线
该代码实现红外遥控器发送信号,在红外接收模块接收到信号后,单片机控制LED灯亮。主要参考了【正点原子】精英STM32F103开发板资料的实验1 跑马灯实验和实验27 红外遥控实验。连接的引脚为:
负极 —> GND
正极 —> 3.3V
输出 —> PB9
总结
在做某工程的开发时,先找到别人已经做好的项目,然后在此基础上实现会轻松很多。正所谓,要站在巨人的肩膀上。