STM32 LED实验代码 笔记

最近开始接触STM32F107VCT6这款ARM Cortex-M3核心的处理器了,实验采用的开发板是神舟IV。神舟IV光盘所带的资料挺完整,演示代码分两个版本,IAR的EWARM和KEIL的MDK版本。 环境所需要的工具什么的都有了,破解版。


首先先搭建好环境,我目前安装的是MDK 4.12  装好后打开源码工程,如下:

这里值得一提的是stm32f10x库封装的很好,很给力。


首先,因为我们将要操作的是LED灯,板载了5个,1个用于电源指示,可供IO口控制的只有4个,分别是LED1,LED2,LED3,LED4,电路图如下:

这些LED等连接到了主控的PD端口,了解了这些将有利于理解下面的代码部分。


系统结构如下:


STM32F107x内存映射如下:


GPIO 映射如下:



代码中用到的外设地址资料如下:

从上面的内存映射图可知,SDRAM_BASE是从0x20000000开始,PERIPH_BASE是 0x40000000开始。

    跟上面的GPIO寄存器映射一致。


GPIOD 端口对应的内存地址为: 0x40000000 + 0x10000 + 0x1400 = 0x40011400。

所有的GPIO端口都处于APB2总线,所以我们的代码在操作LED灯之前先配置APB2。


以下是对代码的分析:

#include "stm32f10x.h" //这个头文件很重要,里面定义了一些宏,管脚,寄存器等。
#include <stdio.h>


/* 
	#define RCC_APB2Periph_GPIOD		((uint32_t)0x00000020)
	#define GPIOD						((GPIO_TypeDef *) GPIOD_BASE)
		#define GPIOD_BASE				(APB2PERIPH_BASE + 0x1400)
		#define APB2PERIPH_BASE			(PERIPH_BASE + 0x10000)
		#define PERIPH_BASE				((uint32_t)0x40000000)
	#define GPIO_Pin_3                 ((uint16_t)0x0008)  
	#define GPIO_Pin_4                 ((uint16_t)0x0010) 
	#define GPIO_Pin_5                 ((uint16_t)0x0020)  
	#define GPIO_Pin_7                 ((uint16_t)0x0080) 
*/


#define RCC_GPIO_LED                                 RCC_APB2Periph_GPIOD
#define GPIO_LED_PORT                                GPIOD    
#define GPIO_LED1                                    GPIO_Pin_2    
#define GPIO_LED2                                    GPIO_Pin_3    
#define GPIO_LED3                                    GPIO_Pin_4    
#define GPIO_LED4                                    GPIO_Pin_7
#define GPIO_LED_ALL                                 GPIO_LED1 |GPIO_LED2 |GPIO_LED3 |GPIO_LED4 

/* 
	操作一个GPIO口,需要配置管脚,速率,以及模式 
	从电路图上可以看出,点亮一个LED灯只需将管脚对应的IO口拉低,反之则关闭LED 
	IO端口以P[A,B,C,D,...,]命名,对应的IO口为PX[0~15],如: PD0 ~ PD15
*/
void LED_config(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  /* Enable GPIOB, GPIOC and AFIO clock */    
  /* RCC_APB2ENR 的第五位是PD端口的使能位 0x200000, 而且是处在APB2总线上*/
  RCC_APB2PeriphClockCmd(RCC_GPIO_LED | RCC_APB2Periph_AFIO , ENABLE);  //RCC_APB2Periph_AFIO
 
  /* LEDs pins configuration */
  /* STM32的GPIO端口在作为输出时,配置端口的时钟速率分别为 2、10、50MHz*/
  GPIO_InitStructure.GPIO_Pin = GPIO_LED_ALL; /* 将实验所用的管脚选中 */
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; /* 配置时钟频率为50MHz ,至于为什么要这么大,暂时还不懂,呵呵*/
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; /* 这个是配置输出模式为推挽输出,既能输出高电平,也能是低电平 */
  GPIO_Init(GPIO_LED_PORT, &GPIO_InitStructure); /* 函数内部配置了对应IO口的输入输出模式和时钟速率 */
}

/*
#ifdef  USE_FULL_ASSERT   //如果定义了这个宏,出现断言错误,会调用assert_failed进行错误捕获。__FILE__ 会替换成当前文件,__LINE__ 是错误行
  #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
  void assert_failed(uint8_t* file, uint32_t line);
#else //如果没有定义这个宏,就什么都不做。
  #define assert_param(expr) ((void)0)
#endif 
*/
/*
stm32f10x_gpio.c 代码中实现
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
	//这个做法,我觉得挺好。在定义了USE_FULL_ASSERT时,能捕获错误。
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); 
  assert_param(IS_GPIO_PIN(GPIO_Pin));
  
  //stm库将寄存器的操作封装成了C语言的结构操作,
  //GPIOx_BRR (bit reset register) 这个寄存器,是位复位寄存器,要将I/O管脚清0复位,只需要将对应的位赋值为1即可。
  //为了方便进行端口的位操作,STM32提供BRR BSRR之类的寄存器去操作ODR的对应位。也可以不这样去使用,直接操作 GPIOx_ODR 寄存器,
  //只是因为这个寄存器需要以字为单位进行访问。类似于51的方式。
  GPIOx->BRR = GPIO_Pin; 
}

//这个函数就是直接对端口进行操作
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal)
{
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  
  GPIOx->ODR = PortVal;
}

//这个函数是将端口对应位置置位。
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  assert_param(IS_GPIO_PIN(GPIO_Pin));
  
  GPIOx->BSRR = GPIO_Pin; //置位/复位寄存器,高16位用于复位(清0),功能和BRR一样。低16位用于置位,对应的是PX0 ~ PX15
}
*/

void Led_Turn_on_all(void)
{
	/* Turn On All LEDs */
    GPIO_ResetBits(GPIO_LED_PORT, GPIO_LED_ALL); //
}

void Led_Turn_on_1(void)
{
	/* Turn On LED1 */
    GPIO_ResetBits(GPIO_LED_PORT, GPIO_LED1);
}

void Led_Turn_on_2(void)
{
	/* Turn On LED2 */
    GPIO_ResetBits(GPIO_LED_PORT, GPIO_LED2 );
}

void Led_Turn_on_3(void)
{
	/* Turn On LED3 */
    GPIO_ResetBits(GPIO_LED_PORT, GPIO_LED3);
}


void Led_Turn_on_4(void)
{
	/* Turn On LED3 */
    GPIO_ResetBits(GPIO_LED_PORT, GPIO_LED4);
}

void Led_Turn_off_all(void)
{
	/* Turn Off All LEDs */
    /* 将这些位拉高,就会关闭LED*/
    GPIO_SetBits(GPIO_LED_PORT, GPIO_LED_ALL);
}

void Led_Turn_on(u8 led)
{
    Led_Turn_off_all();

	/* Turn Off Select LED */
    switch(led)
    {
        case 0:
          Led_Turn_on_1();
          break;

        case 1:
          Led_Turn_on_2();
          break;

        case 2:
          Led_Turn_on_3();
          break;

        case 3:
          Led_Turn_on_4();
          break;
          
        default:
          Led_Turn_on_all();
          break;
    }
}

//这个函数是随便搞点循环进行延时操作
static void Delay_ARMJISHU(__IO uint32_t nCount)
{
  for (; nCount != 0; nCount--);
}

int main(void)
{
  u8 KeyNum = 0;

  LED_config();
  Led_Turn_on_all();
  Delay_ARMJISHU(6000000);
  Led_Turn_off_all();
  Delay_ARMJISHU(6000000);

  KeyNum=0;
  /* Main loop */
  while (1)
  {
      //Led_Turn_on_Hex(KeyNum);
      Led_Turn_off_all();
      Led_Turn_on(KeyNum%4); //从0~3不断变化
      KeyNum++;

      Delay_ARMJISHU(1000000);
  }  
}

//
#ifdef  USE_FULL_ASSERT
void assert_failed(uint8_t* file, uint32_t line)
{ 
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* Infinite loop */
  while (1)
  {
  }
}
#endif

按下 F7 进行编译,然后Ctrl + F5调试运行程序。开发板必须处在打开状态。


总结:

         1。操作GPIO端口,首先需要打开外设总线,这里是APB2总线。

         2。设置输入输出模式,速率。

         3。剩下的就是对GPIO进行输入输出的操作了。

         4。这里的所有操作都依赖于stm32f10x库,对于具体实现只是对寄存器操作的封装,以及内存地址的封装。

         5。这款主控对于IO的操作上与51有些区别,主要体现在端口位操作上,51没有类似于BSRR BRR可直接操作位的寄存器。


本人是新手,刚入手这板子,以上仅是个人学习的一些积累,错误在所难免。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 可以参考这个示例代码:#include "stm32f10x.h"int main(void) { // 初始化 GPIO RCC->APB2ENR |= 0x01; GPIOA->CRL &= 0xFFFFF00F; GPIOA->CRL |= 0x00000300; // 关闭所有中断 NVIC->ICER[0] = 0xFFFFFFFF; NVIC->ICER[1] = 0xFFFFFFFF; // 主循环 while(1) { GPIOA->ODR ^= 0x00000020; for (int i = 0; i < 0x200000; i++); } } ### 回答2: STM32 是一款微控制器系列,其中包含了丰富的外设和功能,其中之一是控制 LED 的闪烁。在 STM32 中,可以使用 GPIO(通用输入输出)模块来实现 LED 的控制。 下面是一个简单的 STM32 LED 闪烁的代码示例: #include "stm32f4xx.h" void delay(uint32_t time) { while(time--); } int main(void) { // 初始化时钟 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); // 配置 PA5 引脚作为输出 GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStruct); while(1) { // 将 PA5 引脚置高,LED 亮起 GPIO_SetBits(GPIOA, GPIO_Pin_5); // 延时一段时间,这里以示例为准,可根据需要调整时间 delay(500000); // 将 PA5 引脚置低,LED 熄灭 GPIO_ResetBits(GPIOA, GPIO_Pin_5); // 延时一段时间,这里以示例为准,可根据需要调整时间 delay(500000); } } 以上代码使用了 STM32F4xx 库来进行硬件初始化和控制。首先,我们需要设置 GPIOA 的时钟,并配置 PA5 引脚为输出模式。 然后,在主循环中,我们使用 GPIO_SetBits 和 GPIO_ResetBits 函数来分别将 PA5 引脚置高和置低,从而控制 LED 的亮灭状态。 最后,通过 delay 函数来实现延时,以控制 LED 闪烁的频率。这里的示例延时为 500,000 个循环,可以根据需要进行调整。 这是一个简单的 STM32 LED 闪烁代码示例,你可以在 STM32 开发板上试用,并根据自身需求进行修改和优化。 ### 回答3: 要实现STM32上的LED闪烁,可以使用GPIO口控制LED的亮灭。 1. 首先,需要在程序中包含相应的头文件,比如"stm32f10x.h"。 2. 接下来,需定义相关的宏,如GPIO端口和引脚号。例如,若LED连接到GPIOB的第5号引脚,则定义如下宏: ``` #define LED_GPIO_PORT GPIOB #define LED_GPIO_PIN GPIO_Pin_5 ``` 3. 初始化相关的GPIO口,使其可用于控制LED。例如,使用如下代码初始化GPIOB的第5号引脚: ``` GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitStructure.GPIO_Pin = LED_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 输出推挽模式 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // GPIO速度为50MHz GPIO_Init(LED_GPIO_PORT, &GPIO_InitStructure); ``` 4. 编写一个死循环,用来闪烁LED。可以使用下述代码: ``` while (1) { GPIO_SetBits(LED_GPIO_PORT, LED_GPIO_PIN); // 点亮LED Delay(500); // 延时一段时间 GPIO_ResetBits(LED_GPIO_PORT, LED_GPIO_PIN); // 关闭LED Delay(500); // 再次延时 } ``` 其中,`Delay`是一个自定义的延时函数,用来控制LED亮灭的频率。可以通过`SysTick`定时器或其他方式实现。 上述代码中,LED会以500毫秒的频率闪烁。即点亮500毫秒,然后熄灭500毫秒,不断循环。 最后,将上述代码烧录到STM32的FLASH中,并启动MCU。LED即可按照代码中的设置进行闪烁。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值