STM32的标准库使用学习

一、STM32F1

1、GPIO配置

用一个LED的输出配置,和按键的输入配置来进行记录。

1)输出

初始化配置

void BspLedInit()
{
   //打开时钟
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
   //初始化IO口
  {
       GPIO_InitTypeDef GPIO_InitStruct;

       GPIO_InitStruct.GPIO_Pin  = GPIO_Pin_13;
       GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
       GPIO_InitStruct.GPIO_Speed= GPIO_Speed_50MHz;

       GPIO_Init(GPIOC,&GPIO_InitStruct);
  }
}

常用API

GPIO_ResetBits(GPIOC,GPIO_Pin_13);
GPIO_SetBits(GPIOC,GPIO_Pin_13);

2)输入

初始化配置

void BspKeyInit()
{
   //打开时钟
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
   //初始化IO口
  {
       GPIO_InitTypeDef GPIO_InitStruct;

       GPIO_InitStruct.GPIO_Pin  = GPIO_Pin_3;
       GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;

       GPIO_Init(GPIOA,&GPIO_InitStruct);
  }
}

常用API

GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_3);

2、外部中断配置

外部中断配置主要包含3个部分,引脚配置、外部中断配置、NVIC配置

void BspExtiInit()
{
   //打开时钟
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
   //引脚初始化
  {
       GPIO_InitTypeDef GPIO_InitStruct;

       GPIO_InitStruct.GPIO_Pin  = GPIO_Pin_0;
       GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;

       GPIO_Init(GPIOA,&GPIO_InitStruct);
  }
   //中断线初始化
  {
       EXTI_InitTypeDef EXTI_InitStructure;

       EXTI_InitStructure.EXTI_Line    = EXTI_Line0;
       EXTI_InitStructure.EXTI_Mode    = EXTI_Mode_Interrupt;
       EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
       EXTI_InitStructure.EXTI_LineCmd = ENABLE;

       EXTI_Init(&EXTI_InitStructure);

       //初始化中断线
       GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);
  }
   //NVIC初始化
  {
       NVIC_InitTypeDef NVIC_InitStructure;

       NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //使能外部中断通道
       NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //抢占优先级2,
       NVIC_InitStructure.NVIC_IRQChannelSubPriority =        0; //子优先级0
       NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道

       NVIC_Init(&NVIC_InitStructure);
  }
}

外部中断函数

void EXTI0_IRQHandler(void)
{
   if(EXTI_GetITStatus(EXTI_Line0)!= RESET)
  {
       delay_ms(10);
       if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==0)
      {
         
      }
       EXTI_ClearITPendingBit(EXTI_Line0);
  }
}

3、定时器中断配置

定时器配置主要包含定时器配置和NVIC配置

void BspTim3Init(uint16_t arr,uint16_t psc)
{
   //时钟初始化
   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
   //定时器初始化
  {
       TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

       TIM_TimeBaseStructure.TIM_Period    =   arr-1;                      //设置自动重装载值
       TIM_TimeBaseStructure.TIM_Prescaler =   psc-1;                    //设置预分频值
       TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;      //设置时钟分割:TDTS = Tck_tim
       TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式

       TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
  }
   //NVIC初始化
  {
       NVIC_InitTypeDef NVIC_InitStructure;

       NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;              //TIM3中断
       NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;    //先占优先级0级
       NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;           //从优先级3级
       NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;              //IRQ通道被使能

       NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器
  }
   //定时器使能以及开启中断
  {
       TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断
       TIM_Cmd(TIM3, ENABLE);                    //使能TIMx
  }
}

定时器中断服务函数

void TIM3_IRQHandler(void)
{
   if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)  //检查TIM3更新中断发生与否
  {
       Tim3Main();
       TIM_ClearITPendingBit(TIM3, TIM_IT_Update );   //清除TIMx更新中断标志
  }
}

4、串口中断配置

串口主要包含引脚初始化、串口配置和NVIC配置

void BspUsartInit(u32 bound)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|
RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟
//GPIO端口设置
{
GPIO_InitTypeDef GPIO_InitStructure;
//USART1_TX GPIOA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);

//USART1_RX GPIOA.10初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
//Usart1 NVIC 配置
{
NVIC_InitTypeDef NVIC_InitStructure;

NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化NVIC寄存器
}
//USART 初始化设置
{
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = bound;//串口波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
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); //初始化串口1
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
USART_Cmd(USART1, ENABLE); //使能串口1
}
}

串口中断服务函数

void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
DebugUsartMain();
EXTI_ClearITPendingBit(USART_IT_RXNE);
}
}

5、Systick延时函数配置

#include "bsp_delay.h"

static u8 fac_us=0; //us延时倍乘数
static u16 fac_ms=0; //ms延时倍乘数,在ucos下,代表每个节拍的ms数

void DelayInit()
{
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //选择外部时钟 HCLK/8
fac_us=SystemCoreClock/8000000; //为系统时钟的1/8
fac_ms=(u16)fac_us*1000; //非OS下,代表每个ms需要的systick时钟数
}

void DelayUs(u32 nus)
{
u32 temp;
SysTick->LOAD=nus*fac_us; //时间加载
SysTick->VAL=0x00; //清空计数器
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数
do
{
temp=SysTick->CTRL;
} while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
//延时nms
//注意nms的范围
//SysTick->LOAD为24位寄存器,所以,最大延时为:
//nms<=0xffffff*8*1000/SYSCLK
//SYSCLK单位为Hz,nms单位为ms
//对72M条件下,nms<=1864
void DelayMs(u16 nms)
{
u32 temp;
SysTick->LOAD=(u32)nms*fac_ms; //时间加载(SysTick->LOAD为24bit)
SysTick->VAL =0x00; //清空计数器
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数
do
{
temp=SysTick->CTRL;
} while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}

6、位操作配置

#ifndef _BSP_SYS_H
#define _BSP_SYS_H

#include "stm32f10x.h"

//位带操作,实现51类似的GPIO控制功能
//具体实现思想,参考<<CM3权威指南>>第五章(87页~92页).
//IO口操作宏定义
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
//IO口地址映射
#define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C
#define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C
#define GPIOC_ODR_Addr (GPIOC_BASE+12) //0x4001100C
#define GPIOD_ODR_Addr (GPIOD_BASE+12) //0x4001140C
#define GPIOE_ODR_Addr (GPIOE_BASE+12) //0x4001180C
#define GPIOF_ODR_Addr (GPIOF_BASE+12) //0x40011A0C
#define GPIOG_ODR_Addr (GPIOG_BASE+12) //0x40011E0C

#define GPIOA_IDR_Addr (GPIOA_BASE+8) //0x40010808
#define GPIOB_IDR_Addr (GPIOB_BASE+8) //0x40010C08
#define GPIOC_IDR_Addr (GPIOC_BASE+8) //0x40011008
#define GPIOD_IDR_Addr (GPIOD_BASE+8) //0x40011408
#define GPIOE_IDR_Addr (GPIOE_BASE+8) //0x40011808
#define GPIOF_IDR_Addr (GPIOF_BASE+8) //0x40011A08
#define GPIOG_IDR_Addr (GPIOG_BASE+8) //0x40011E08

//IO口操作,只对单一的IO口!
//确保n的值小于16!
#define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //输出
#define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //输入

#define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //输出
#define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //输入

#define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) //输出
#define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //输入

#define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) //输出
#define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //输入

#define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) //输出
#define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //输入

#define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //输出
#define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //输入

#define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) //输出
#define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //输入

//以下为汇编函数
void WFI_SET(void); //执行WFI指令
void INTX_DISABLE(void);//关闭所有中断
void INTX_ENABLE(void); //开启所有中断
void MSR_MSP(u32 addr); //设置堆栈地址

#endif

7、ADC配置

ADC配置包括引脚初始化和ADC初始化

void BspAdcInit(void)
{
//时钟初始化
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA
|RCC_APB2Periph_ADC1 , ENABLE ); //使能ADC1通道时钟
//GPIO初始化
{
GPIO_InitTypeDef GPIO_InitStructure;

//PA1 作为模拟通道输入引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入引脚
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
//ADC 初始化
{
ADC_InitTypeDef ADC_InitStructure;

RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M
ADC_DeInit(ADC1); //复位ADC1

ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作模式:ADC1和ADC2工作在独立模式
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //模数转换工作在单通道模式
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //模数转换工作在单次转换模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = 1; //顺序进行规则转换的ADC通道的数目
ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器

ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1

ADC_ResetCalibration(ADC1); //使能复位校准

while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束

ADC_StartCalibration(ADC1); //开启AD校准

while(ADC_GetCalibrationStatus(ADC1)); //等待校准结束

// ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能
}
}

常用函数

//获得ADC值
//ch:通道值 0~3
u16 GetAdc(u8 ch)
{
//设置指定ADC的规则组通道,一个序列,采样时间
ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 ); //ADC1,ADC通道,采样时间为239.5周期

ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能

while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束

return ADC_GetConversionValue(ADC1); //返回最近一次ADC1规则组的转换结果
}

 


__EOF__

本文作者Snqx-lqh
本文链接https://www.cnblogs.com/snqx-lqh/p/15872748.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   少年-潜行  阅读(486)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
点击右上角即可分享
微信分享提示