STM32F10x_StdPeriph_Lib_V3.6.0
1> 外设驱动
ST公司为STM32F103中所有的外设,都编写了1个.c和.h的驱动文件
先学会用他,再研究研究他是怎么个事,
最后用用他的套路,写写开发板的外设比如LED,按键,液晶屏等
2> 头文件包含关系
1个头文件stm32f10x.h 就把整个MCU以及标准外设库,就管理了;
3> .c文件内部结构
/** ****************************************************************************** * @file Project/STM32F10x_StdPeriph_Template/stm32f10x_it.c * @author MCD Application Team * @version V3.6.0 * @date 20-September-2021 * @brief Main Interrupt Service Routines. * ****************************************************************************** * @attention * ****************************************************************************** */
【段】文件头注释
/* Includes -------------------------------*/
【段】包含头文件
/* Private typedef ------------------------*/
【段】内部类型重命名
/* Private define -------------------------*/
【段】内部宏定义
/* Private macro --------------------------*/
【段】内部预处理,宏函数
/* Private variables ----------------------*/
【段】内部变量定义
/* Private function prototypes ------------*/
【段】内部函数声明
/* Private functions ----------------------*/
【段】函数实现
4> 宏定义位置
有些宏定义在.c文件中,有些在 .h文件中,没规律吗?
例如:
// stm32f10xx_gpio.c:
#define MAPR_OFFSET (AFIO_OFFSET + 0x04)
// stm32f10xx_gpio.h:
#define GPIO_Pin_0 ((uint16_t)0x0001)
如果宏定义只用在自己的.c文件中,定义到.c文件中,
如果要被其他文件用,就定义在.h文件中;
5> 位掩码bit mask
时钟控制寄存器RCC_CR的bit18【HSEBYP】
// 文件 stm32f10x_rcc.c
// 位掩码定义
#define CR_HSEBYP_Reset ((uint32_t)0xFFFBFFFF) // bit18 == 0;
#define CR_HSEBYP_Set ((uint32_t)0x00040000) // bit18 == 1;
位掩码使用:
/* Set HSEBYP */
RCC->CR |= CR_HSEBYP_Set;
/* Reset HSEBYP bit */
RCC->CR &= CR_HSEBYP_Reset;
ST公司工程师为了不进行移位操作,定义好位掩码;
比如,
想要让CR寄存器的bit18等于1,就 |= 0x00040000;
想要让CR寄存器的bit18等于0,就&= FFFBFFFF;
往后,咱也用用这招;
6> .c文件中定义私有变量
文件 stm32f10x_rcc.c
/** @defgroup RCC_Private_Variables * @{ */
static __I uint8_t APBAHBPrescTable[16] = {
0, 0, 0, 0, 1, 2, 3, 4, 1, 2, 3, 4, 6, 7, 8, 9};
static __I uint8_t ADCPrescTable[4] = {
2, 4, 6, 8};
static原来这样使啊!Private /ˈpraɪvət/
7> 枚举类型定义
typedef enum {
ERROR = 0, SUCCESS = !ERROR} ErrorStatus;
ErrorStatus RCC_WaitForHSEStartUp(void)
{
__IO uint32_t StartUpCounter = 0;
ErrorStatus status = ERROR;
FlagStatus HSEStatus = RESET;
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC_GetFlagStatus(RCC_FLAG_HSERDY);
StartUpCounter++;
} while((StartUpCounter != HSE_STARTUP_TIMEOUT) && (HSEStatus == RESET));
if (RCC_GetFlagStatus(RCC_FLAG_HSERDY) != RESET)
{
status = SUCCESS;
}
else
{
status = ERROR;
}
return (status);
}
枚举类型,就是给参数画个圈,固定几个数;
最大的好处就是,传递的参数明确,如果传错,编译时就会报错,
让你及时发现错误
8> 注释风格
采用“Doxygen”的注释规范,方便Doxgen软件自动根据注释生成帮助文档
/** * @brief Checks whether the specified RCC flag is set or not. * @param RCC_FLAG: specifies the flag to check. * * For @b STM32_Connectivity_line_devices, this parameter can be one of the * following values: * @arg RCC_FLAG_HSIRDY: HSI oscillator clock ready * * @retval The new state of RCC_FLAG (SET or RESET). */
FlagStatus RCC_GetFlagStatus(uint8_t RCC_FLAG){
}
9> 函数命名规律
9.1> 初始化函数 Init
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct);
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);
模块名_Init ( 模块名_InitTypeDef * )
9.2> 使能模块函数 Cmd
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState);
模块名_xxxCmd(FunctionalState)
9.3> 使能模块中断 ITConfig
void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState);
void I2C_ITConfig(I2C_TypeDef* I2Cx, uint16_t I2C_IT, FunctionalState NewState);
文章评论