首页 > 软件学院 > 单片机 > STM32

STM32跑马灯实验大致可以分为三个步骤,1. LED初始化,2.延时函数的编写,3.主函数编写

钱平海STM32 2020-06-27 13:10:16STM32
新手接触单片机练习的一个跑马灯实验,虽然实验并不难,但开始却并不容易,跑马灯实验对于程序员高手来说简直小菜一碟。可这对于一个不懂硬件的新手来说,真的不容易,需要多学习和了解才能快速上手。学习的同时可以参考STM32中文参考手册_V10,也可以看Cortex-M3权威指南。慢慢的明白了其中的原理,也知道了为什么要配置成上拉、下拉、推挽输出、复用推挽输出,了解整个过程,这样上手就会快很多。
跑马灯实验大致可以分为三个步骤:
1. LED初始化/led.h文件
LED初始化包括时钟初始化和引脚初始化。每一个外设都有其对应的时钟,所以在使用外设之前都要先开启外设的时钟。
引脚初始化(端口初始化),本实验是要通过引脚输出高低电平来控制LED的亮灭。端口初始化主要是配置:输出引脚、输出模式、输出速率。
初始化代码如下:
 
/*本次跑马灯实验主要用到PB6~PB9几个端口*/
#include "LED.h"
 
void LED_Init(void)  //自定义Led灯初始化函数
{  
    GPIO_InitTypeDef  GPIO_InitStructure;  
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOA, ENABLE); /*使能LED灯使用的GPIO时钟*/     
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9;   
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出模式  
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  //以上为配置GPIO
    GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIOB 
}
附上头文件:
 
/*头文件中主要是一些宏定义和位带操作*/
#ifndef __LED_H
#define __LED_H
 
#include "stm32f10x.h"
 
#define LED1_ON GPIO_SetBits(GPIOB, GPIO_Pin_6)
#define LED1_OFF GPIO_ResetBits(GPIOB, GPIO_Pin_6)
#define LED2_ON GPIO_SetBits(GPIOB, GPIO_Pin_7)
#define LED2_OFF GPIO_ResetBits(GPIOB, GPIO_Pin_7)
#define LED3_ON GPIO_SetBits(GPIOB, GPIO_Pin_8)
#define LED3_OFF GPIO_ResetBits(GPIOB, GPIO_Pin_8)
#define LED4_ON GPIO_SetBits(GPIOB, GPIO_Pin_9)
#define LED4_OFF GPIO_ResetBits(GPIOB, GPIO_Pin_9)
	 
//位带操作,实现51类似的GPIO控制功能
//具体实现思想,参考<>第五章(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)  //输入
 
#define LED1  PBout(6)
#define LED2  PBout(7)
#define LED3  PBout(8)
#define LED4  PBout(9)
 
void LED_Init(void);
 
#endif

2.延时函数的编写/led.c文件
跑马灯实验中需要用到延时函数,这个网上有很多例子。下面给出一个比较常用且精准的延时函数。有兴趣的也可以自己去编写属于自己的延时函数。这个函数比较常用,在后面的实验中也会经常用到。
源文件:
#include "delay.h"
 
void delay_us(u32 nus)
{
	u32 temp;
	SysTick->LOAD = 9*nus;
	SysTick->VAL=0X00;//清空计数器
	SysTick->CTRL=0X01;//使能,减到零是无动作,采用外部时钟源
	do
	{
		temp=SysTick->CTRL;//读取当前倒计数值
	}while((temp&0x01)&&(!(temp&(1<<16))));//等待时间到达
    SysTick->CTRL=0x00; //关闭计数器
    SysTick->VAL =0X00; //清空计数器
}
 
void delay_ms(u16 nms)
{
	u32 temp;
	SysTick->LOAD = 9000*nms;
	SysTick->VAL=0X00;//清空计数器
	SysTick->CTRL=0X01;//使能,减到零是无动作,采用外部时钟源
	do
	{
		temp=SysTick->CTRL;//读取当前倒计数值
	}while((temp&0x01)&&(!(temp&(1<<16))));//等待时间到达
    SysTick->CTRL=0x00; //关闭计数器
    SysTick->VAL =0X00; //清空计数器
}
头文件:
#ifndef __DELAY_H
#define __DELAY_H
 
#include "stm32f10x.h"
 
void delay_us(u32 nus);
void delay_ms(u16 nms);
 
#endif
3.主函数编写/main.c文件
主函数就比较简单了,先调用LED的初始化函数,然后依次点亮LED。
/*引用头文件是为了调用其中定义的函数*/
#include "stm32f10x.h"
#include "delay.h"
#include "led.h"
 
int main(void)
{   
    LED_Init(); 
    while(1)
    {     
        LED1 = 1;
        delay_ms(200);
        LED1 = 0;
        delay_ms(200);
        LED2 = 1;
        delay_ms(200);
        LED2 = 0;
        delay_ms(200);
        LED3 = 1;
        delay_ms(200);
        LED3 = 0;
        delay_ms(200);
        LED4 = 1;
        delay_ms(200);
        LED4 = 0;
        delay_ms(200);
    }   
}
跑马灯实验就结束了。新手不可完全照搬,要根据自己的原理图来做对程序做相应的修改,加入自己的思考,才会真正成为自己的东西。
版权声明:

!!!未经七天PCB网允许,不得复制或盗链本网站,本站所提供的技术文章,视频教程,软件资源等内容均为作者原创提供。

留言与评论(共有 0 条评论)
   
验证码:

七天PCB网

http://www.pcb.wang/

电子电路 | 电子硬件PCB工程

Powered By 七天PCB网 电子电路技术爱好者

使用手机软件扫描微信二维码

关注我们可获取更多电子知识

感谢各位对七天PCB网的支持