1、LED模块篇(STM32)

前提:文件创建


创建顺序:
keil新建文件夹里面起工程名“Project”,保存。
选择芯片:STM32F103C8
在文件管理给刚刚建立的工程夹把模板Start、Library、User文件粘贴进来
点击魔术棒右边的三个箱子图案(文件管理按钮)
把默认组(SourceGroup1)叉掉,点叉左边的按钮新建三个组:Start、Libaray、User
Start里添加文件:startup_stm32f10x_md.s
                            core_cm3.c
                            core_cm3.h
                            stm32f10x.h
                            system_stm32f10x.c
                            system_stm32f10x.h
Libaray里添加文件:全部Libaray文件
User里添加文件:全部User文件
点击魔术棒 ——> c/c++ ——>Include Paths:添加Start、Library、User;然后Define:USE_STDPERIPH_DRIVER(USE使用、STD标准、PERIPH外设、DRIVER驱动)——>
Debug:调试器(右上角):STLINK,点击右边settings->Flash Download把Reset and run

1、点亮LED加闪烁

主要用RCC和GPIO口两个外设

使用GPIO口有三个步骤:

(1)使用RCC开启GPIO的时钟

(2)使用GPIO_Init函数初始化GPIO

(3)使用输出或者输入的函数控制GPIO口

了解:

#1:打开Library下面的stm32f10_rcc.h(.h文件里面的最下面一般都是库函数所有函数的声明)

最常用的三个函数()为:

692|void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState);
693|void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
694|void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);

点击RCC_AHBPeriphClockCmd跳转看到函数的介绍,这个AHB外设时钟控制的函数就是使能或失能AHB外设时钟的,第一个参数选择外设,第二个参数选择使能或失能,下方列表(1039行以下@arg)有外设连接到哪个总线。

1
/**
  * @brief  Enables or disables the AHB peripheral clock.
  * @param  RCC_AHBPeriph: specifies the AHB peripheral to gates its clock.
  *   
  *   For @b STM32_Connectivity_line_devices, this parameter can be any combination
  *   of the following values:        
  *     @arg RCC_AHBPeriph_DMA1
  *     @arg RCC_AHBPeriph_DMA2
  *     @arg RCC_AHBPeriph_SRAM
  *     @arg RCC_AHBPeriph_FLITF
  *     @arg RCC_AHBPeriph_CRC
  *     @arg RCC_AHBPeriph_OTG_FS    
  *     @arg RCC_AHBPeriph_ETH_MAC   
  *     @arg RCC_AHBPeriph_ETH_MAC_Tx
  *     @arg RCC_AHBPeriph_ETH_MAC_Rx
  * 
  *   For @b other_STM32_devices, this parameter can be any combination of the 
  *   following values:        
  *     @arg RCC_AHBPeriph_DMA1
  *     @arg RCC_AHBPeriph_DMA2
  *     @arg RCC_AHBPeriph_SRAM
  *     @arg RCC_AHBPeriph_FLITF
  *     @arg RCC_AHBPeriph_CRC
  *     @arg RCC_AHBPeriph_FSMC
  *     @arg RCC_AHBPeriph_SDIO
  *   
  * @note SRAM and FLITF clock can be disabled only during sleep mode.
  * @param  NewState: new state of the specified peripheral clock.
  *   This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_RCC_AHB_PERIPH(RCC_AHBPeriph));
  assert_param(IS_FUNCTIONAL_STATE(NewState));

  if (NewState != DISABLE)
  {
    RCC->AHBENR |= RCC_AHBPeriph;
  }
  else
  {
    RCC->AHBENR &= ~RCC_AHBPeriph;
  }
}
2
/**
  * @brief  Enables or disables the High Speed APB (APB2) peripheral clock.
  * @param  RCC_APB2Periph: specifies the APB2 peripheral to gates its clock.
  *   This parameter can be any combination of the following values:
  *     @arg 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     
  * @param  NewState: new state of the specified peripheral clock.
  *   This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph));
  assert_param(IS_FUNCTIONAL_STATE(NewState));
  if (NewState != DISABLE)
  {
    RCC->APB2ENR |= RCC_APB2Periph;
  }
  else
  {
    RCC->APB2ENR &= ~RCC_APB2Periph;
  }
}
3
/**
  * @brief  Enables or disables the Low Speed APB (APB1) peripheral clock.
  * @param  RCC_APB1Periph: specifies the APB1 peripheral to gates its clock.
  *   This parameter can be any combination of the following values:
  *     @arg 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
  * @param  NewState: new state of the specified peripheral clock.
  *   This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_RCC_APB1_PERIPH(RCC_APB1Periph));
  assert_param(IS_FUNCTIONAL_STATE(NewState));
  if (NewState != DISABLE)
  {
    RCC->APB1ENR |= RCC_APB1Periph;
  }
  else
  {
    RCC->APB1ENR &= ~RCC_APB1Periph;
  }
}

#2:打开stm32f10x_gpio.h文件,下面的“四void+四uint+四void”这个12个文件为常用的函数:

​
349|void GPIO_DeInit(GPIO_TypeDef* GPIOx);//调用后GPIO外设就会被复位
350|void GPIO_AFIODeInit(void);//可以复位AFIO外设
351|void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
    //第三个非常重要,用结构体的参数来初始化GPIO口。需要先定义一个结构体变量,然后再给结构体赋值, 
    //最后调用这个函数,这个函数内部就会自动读取结构体的值,然后自动把外设的各个参数配置好,这种 
    //Init函数在stm32基本所有的外设都有,一般初始化外设都是使用这个Init函数来完成的
352|void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct);//第四个可以把结构体变量赋一个默认 
                                                            //值
    //接下来四个uint就是GPIO的读取函数,再下面四个void就是GPIO的写入函数
353|uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
354|uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
355|uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
356|uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);
357|void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
358|void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
359|void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
360|void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);
    //上面8个函数就可以实现读写GPIO口的功能

​

//第一个,调用后GPIO外设就会被复位

//第二个,可以复位AFIO外设

//第三个非常重要,用结构体的参数来初始化GPIO口。需要先定义一个结构体变量,然后再给结构体赋值,最后调用这个函数,这个函数内部就会自动读取结构体的值,然后自动把外设的各个参数配置好,这种Init函数在stm32基本所有的外设都有,一般初始化外设都是使用这个Init函数来完成的。

//第四个可以把结构体变量赋一个默认值

//接下来四个uint就是GPIO的读取函数,再下面四个void就是GPIO的写入函数,上面8个函数就可以实现读写GPIO口的功能

点亮LED:

第一种方式,用(第三个后void)GPIO_WriteBit,设置第三个参数Bit_RESET为低电平,Bit_SET为高电平

#include "stm32f10x.h"
#include "Delay.h"

int main(){
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//开启时钟(外设,状态)=(GPIO A口,            
                                                        //使能)
	GPIO_InitTypeDef GPIO_InitStructure;//建立一个结构体
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//状态:推挽输出
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//引脚
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//输出速度
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	//GPIO_ResetBits(GPIOA,GPIO_Pin_0);//设置低电平
	//GPIO_SetBits(GPIOA,GPIO_Pin_0);//设置高电平
	
	//GPIO_Write(GPIOA, PortVal);
	while(1){
		GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET);
		Delay_ms(500);
		GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
		Delay_ms(500);
	}
}	

如果我们非要给一个数,1是高电平,0是低电平。我们可以将Bit_SET改成1,Bit_RESET改成0,但如果直接这样编译的话会有两个警告,说的是枚举类型中混进了其他类型的变量,所以如果想直接写1和0的话,需要在这里加上强制类型转换,即改成(BitAction)0和(BitAction)1,将1和0类型转换为BitAction的枚举类型。代码如下:

GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)0);
Delay_ms(500);
GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)1);
Delay_ms(500);

第二种方式用第一个后void函数和第二个后void函数,即用GPIO_SetBits和GPIO_ResetBits两个函数来设置

GPIO_SetBits(GPIOA,GPIO_Pin_0);//设置高电平	
GPIO_ResetBits(GPIOA,GPIO_Pin_0);//设置低电平

在这里可以讨论以下推挽输出和开漏输出的驱动问题:

将LED灯引脚拔掉,两个引脚互换位置插到面包板,此时LED就是高电平点亮的方式,可以看到LED正常闪烁,说明在推挽模式下,高低电平都有驱动能力。

然后我们把这个端口的模式换成Out_OD,开漏输出模式,再编译下载,此时LED还是高电平点亮方式,但LED不亮,说明开漏输出的模式下高电平是没有驱动能力的,再把LED引脚插入位置改回(即低电平点亮方式),LED亮,说明开漏模式的低电平是有驱动能力的。

这就印证的推挽输出和开漏输出的特性,推挽输出高低电平都有驱动能力,开漏输出高电平相当于高阻态,没有驱动能力,低电平有驱动能力。一般输出用推挽模式就行了,特殊的地方才会用到开漏模式。

LED流水灯

当GPIO要引用多个引脚时,可以用或来连接引脚定义:                    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;                (可以这样子的原因:打开定义看,Pin0对应的数据是0x0001,然后Pin1、Pin2、Pin3依次为0x0002、0x0004、0x0008,如果把这个16进制换成二进制,就是0000 0000 0000 0001,然后是0010、0100、1000,在这里每个端口对应一个位,如果把他们进行按位或的操作,比如Pin0、Pin1和Pin2按位或,那结果就是0111,这样就相当于同时选中了3个端口,这就是按位或的操作逻辑,最后看到有个GPIO_Pin_All,它对应的数据就是0xFFFF,也就是所有位都为1,这样就相当于选中了所有引脚,在这里除了这个GPIO_Pin可以按位或的操作方式外,时钟控钟RCC_APB2PeriphResetCmd的这一项,也是可以用按位或的方式来选择多个外设,它的定义和GPIO参数的一样,数据的规律是每一位对应一个外设,还有GPIO_SetBits)

GPIO_Pin:

#define GPIO_Pin_0        ((uint16_t)0x0001)  /*!< Pin 0 selected */
#define GPIO_Pin_1        ((uint16_t)0x0002)  /*!< Pin 1 selected */
#define GPIO_Pin_2        ((uint16_t)0x0004)  /*!< Pin 2 selected */
#define GPIO_Pin_3        ((uint16_t)0x0008)  /*!< Pin 3 selected */

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//开启时钟(外设,状态)=(GPIO A口,使能)点击第一个参数(外设)

#define RCC_APB2Periph_AFIO              ((uint32_t)0x00000001)
#define RCC_APB2Periph_GPIOA             ((uint32_t)0x00000004)
#define RCC_APB2Periph_GPIOB             ((uint32_t)0x00000008)
#define RCC_APB2Periph_GPIOC             ((uint32_t)0x00000010)
#define RCC_APB2Periph_GPIOD             ((uint32_t)0x00000020)
#define RCC_APB2Periph_GPIOE             ((uint32_t)0x00000040)

现在为了同时控制16个端口,我们就可以使用GPIO_Write这个函数,第一个参数是GPIOx,我们直接写GPIOA,第二个参数转到定义看到:

414|* @param  PortVal: specifies the value to be written to the port output data register.

这里写的是,指定写到输出数据寄存器的值,下面看到:GPIOx->ODR = PortVal;这第二个参数就是直接写到GPIO的ODR寄存器里的,所以我们可以直接写0x0001,对应二进制就是0000 0000 0000 0001;(c语言不支持直接写二进制,所以这里只能转换为十六进制来写),这十六个二进制分别对应PA0到PA15总共16个端口,最低位对应PA0,然后往上依次是PA1,PA2,一直到PA15,因为是低电平点亮,所以前面再加一个按位取反的符号~。 

	while(1){
		GPIO_Write(GPIOA,~0x0001);//0000 0000 0000 0001
		Delay_ms(500);
		GPIO_Write(GPIOA,~0x0002);//0000 0000 0000 0010
		Delay_ms(500);
		GPIO_Write(GPIOA,~0x0004);//0000 0000 0000 0100
		Delay_ms(500);
		GPIO_Write(GPIOA,~0x0008);//0000 0000 0000 1000
		Delay_ms(500);
		GPIO_Write(GPIOA,~0x0010);//0000 0000 0001 0000
		Delay_ms(500);
		GPIO_Write(GPIOA,~0x0020);//0000 0000 0010 0000
		Delay_ms(500);
		GPIO_Write(GPIOA,~0x0040);//0000 0000 0100 0000
		Delay_ms(500);
		GPIO_Write(GPIOA,~0x0080);//0000 0000 1000 0000
		Delay_ms(500);
		
	}

2、蜂鸣器

#include "stm32f10x.h"
#include "Delay.h"
int main(){
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能时钟,开启外设时钟
    //(选择外设,选择新的状态)
	GPIO_InitTypeDef GPIO_InitStructure;//定义结构体
	GPIO_InitStructure.GPIO_Mode=  GPIO_Mode_Out_PP;//GPIO模式=通用推挽输出
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;//GPIO端口=(跳转定义时选member)
    //这里随便选一个口,但A15\B3\B4有特殊定义,这三个口默认是TTAG的调试端口,
    //如果要用作普通端口的话,需要进行配置
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//GPIO速度
	GPIO_Init(GPIOB,&GPIO_InitStructure);//配置端口模式(选择GPIO,选择参数的结构体)
	while(1){
		GPIO_ResetBits(GPIOB,GPIO_Pin_12);
		Delay_ms(100);
		GPIO_SetBits(GPIOB,GPIO_Pin_12);
		Delay_ms(100);
		GPIO_ResetBits(GPIOB,GPIO_Pin_12);
		Delay_ms(100);
		GPIO_SetBits(GPIOB,GPIO_Pin_12);
		Delay_ms(100);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值