STM32学习笔记(二)



  • 0_1597487937494_1f0f0307-0954-469f-8b87-463e52673d25-image.png
    0_1597487984277_ae2e5d64-b8a1-4a2d-b348-09721a83bfbd-image.png PS:其实很多程序之前自己开发时都做过,使用开发板之后,还是决定重新做一遍,顺便扎实基础

    野火开发板闪灯程序
    原理:

    如图所示,开发板用PB0,PB1,PB5三个GPIO端口控制了三个LED,这三个LED组成了RGB灯

    PB0:绿色
    PB1:红色
    PB5:蓝色

    通过颜色混合,可以得到多种颜色(如:紫色=红色+蓝色)
    跟随开发板教程的思路,完成LED驱动代码:
    led.h:
    #ifndef __LED_H
    #define __LED_H

    #include <stm32f10x.h>

    // R-红色
    #define LED1_GPIO_PORT GPIOB
    #define LED1_GPIO_CLK RCC_APB2Periph_GPIOB
    #define LED1_GPIO_PIN GPIO_Pin_5
    // G-绿色
    #define LED2_GPIO_PORT GPIOB
    #define LED2_GPIO_CLK RCC_APB2Periph_GPIOB
    #define LED2_GPIO_PIN GPIO_Pin_0
    // B-蓝色
    #define LED3_GPIO_PORT GPIOB
    #define LED3_GPIO_CLK RCC_APB2Periph_GPIOB
    #define LED3_GPIO_PIN GPIO_Pin_1

    /* 直接操作寄存器的方法控制 IO /
    #define digitalHi(p,i) {p->BSRR=i;} //输出为高电平
    #define digitalLo(p,i) {p->BRR=i;} //输出低电平
    #define digitalToggle(p,i) {p->ODR ^=i;} //输出反转状态
    /
    定义控制 IO 的宏 */
    #define LED1_TOGGLE digitalToggle(LED1_GPIO_PORT,LED1_GPIO_PIN)
    #define LED1_OFF digitalHi(LED1_GPIO_PORT,LED1_GPIO_PIN)
    #define LED1_ON digitalLo(LED1_GPIO_PORT,LED1_GPIO_PIN)

    #define LED2_TOGGLE digitalToggle(LED2_GPIO_PORT,LED2_GPIO_PIN)
    #define LED2_OFF digitalHi(LED2_GPIO_PORT,LED2_GPIO_PIN)
    #define LED2_ON digitalLo(LED2_GPIO_PORT,LED2_GPIO_PIN)

    #define LED3_TOGGLE digitalToggle(LED2_GPIO_PORT,LED3_GPIO_PIN)
    #define LED3_OFF digitalHi(LED2_GPIO_PORT,LED3_GPIO_PIN)
    #define LED3_ON digitalLo(LED2_GPIO_PORT,LED3_GPIO_PIN)

    /* 基本混色,后面高级用法使用 PWM 可混出全彩颜色,且效果更好 */
    //红
    #define LED_RED
    LED1_ON;
    LED2_OFF
    LED3_OFF
    //绿
    #define LED_GREEN
    LED1_OFF;
    LED2_ON
    LED3_OFF
    //蓝
    #define LED_BLUE
    LED1_OFF;
    LED2_OFF
    LED3_ON
    //黄(红+绿)
    #define LED_YELLOW
    LED1_ON;
    LED2_ON
    LED3_OFF
    //紫(红+蓝)
    #define LED_PURPLE
    LED1_ON;
    LED2_OFF
    LED3_ON
    //青(绿+蓝)
    #define LED_CYAN
    LED1_OFF;
    LED2_ON
    LED3_ON
    //白(红+绿+蓝)
    #define LED_WHITE
    LED1_ON;
    LED2_ON
    LED3_ON
    //黑(全部关闭)
    #define LED_RGBOFF
    LED1_OFF;
    LED2_OFF
    LED3_OFF

    void LED_GPIO_Config(void){
    /定义一个 GPIO_InitTypeDef 类型的结构体/
    GPIO_InitTypeDef GPIO_InitStructure;
    /开启 LED 相关的 GPIO 外设时钟/
    RCC_APB2PeriphClockCmd( LED1_GPIO_CLK|LED2_GPIO_CLK|LED3_GPIO_CLK, ENABLE);

    /*选择要控制的 GPIO 引脚*/
    GPIO_InitStructure.GPIO_Pin = LED1_GPIO_PIN;
    /*设置引脚模式为通用推挽输出*/
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    /*设置引脚速率为 50MHz */
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    /*调用库函数,初始化 GPIO*/
    GPIO_Init(LED1_GPIO_PORT, &GPIO_InitStructure);
    /* 关闭所有 led 灯   */
    GPIO_SetBits(LED1_GPIO_PORT, LED1_GPIO_PIN);
    
    /*选择要控制的 GPIO 引脚*/
    GPIO_InitStructure.GPIO_Pin = LED2_GPIO_PIN;
         /*调用库函数,初始化 GPIO*/
    GPIO_Init(LED2_GPIO_PORT, &GPIO_InitStructure);
    /* 关闭所有 led 灯   */
    GPIO_SetBits(LED2_GPIO_PORT, LED2_GPIO_PIN);
    
    /*选择要控制的 GPIO 引脚*/
    GPIO_InitStructure.GPIO_Pin = LED3_GPIO_PIN;
    /*调用库函数,初始化 GPIOF*/
    GPIO_Init(LED3_GPIO_PORT, &GPIO_InitStructure);
    /* 关闭所有 led 灯   */
    GPIO_SetBits(LED3_GPIO_PORT, LED3_GPIO_PIN);
    

    }

    #endif

    其中,发现有一处存在缺陷,这是在做按键检测时发现的,按键检测时,按下复位键,发现LED快速闪烁一下后熄灭,分析原因,是因为原代码中,先对所有用到的GPIO进行了初始化,最后再将电平拉高,由于初始化默认低电平,而恰好满足低电平点灯,低电平没有及时被拉高,因此观测到了闪烁,解决方法就是,初始化一个GPIO端口之后,立刻将该端口电平拉高,然后再初始化下一个端口

    主函数部分
    main.c

    #include <stm32f10x.h>
    #include "led.h"

    #define SOFT_DELAY Delay(0xFFFFFF);
    void Delay(__IO u32 nCount);
    /**

    • @brief 主函数
    • @param 无
    • @retval 无
      */

    int main(void){
    /* LED 端口初始化 */
    LED_GPIO_Config();
    while (1){
    LED_RED; //红
    SOFT_DELAY;
    LED_YELLOW; //黄
    SOFT_DELAY;
    LED_GREEN; //绿
    SOFT_DELAY;
    LED_CYAN; //青
    SOFT_DELAY;
    LED_BLUE; //蓝
    SOFT_DELAY;
    LED_PURPLE; //紫
    SOFT_DELAY;
    LED_WHITE; //白
    SOFT_DELAY;
    }
    }

    void Delay(__IO uint32_t nCount) //简单的延时函数
    {
    for(; nCount != 0; nCount--);
    }

    0_1597488058120_8c8afccc-d090-4a58-93b2-ba51462e95b8-image.png

    原理:
    按键检测最重要的是消抖,开发板通过设计电容,从硬件层面上消除了抖动,否则需要软件消抖,即,接收到低电平信号之后,通过延时程序,等待一小段时间,再进行电平检测,若仍为低电平,则说明按键确实按下了。
    个人认为软件消抖存在局限性,占用了单片机的工作时间,影响单片机的工作效率,不如硬件消抖
    0_1597488180287_149a6382-189e-425e-b225-efda5710a4e5-image.png

    如何直观地表现出检测到按键按下呢?
    利用LED,如果按键一被按下,则LED1亮,若按键二被按下,则LED2亮

    button.h
    #include <stm32f10x.h>

    // 引脚定义
    #define KEY1_GPIO_CLK RCC_APB2Periph_GPIOA
    #define KEY1_GPIO_PORT GPIOA
    #define KEY1_GPIO_PIN GPIO_Pin_0

    #define KEY2_GPIO_CLK RCC_APB2Periph_GPIOC
    #define KEY2_GPIO_PORT GPIOC
    #define KEY2_GPIO_PIN GPIO_Pin_13

    void Key_GPIO_Config(void){
    GPIO_InitTypeDef GPIO_InitStructure;

    /*开启按键端口的时钟*/
    RCC_APB2PeriphClockCmd(KEY1_GPIO_CLK|KEY2_GPIO_CLK,ENABLE);
    //选择按键的引脚
    GPIO_InitStructure.GPIO_Pin = KEY1_GPIO_PIN;
    // 设置按键的引脚为浮空输入
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    //使用结构体初始化按键 
    GPIO_Init(KEY1_GPIO_PORT, &GPIO_InitStructure);
    
    //选择按键的引脚
    GPIO_InitStructure.GPIO_Pin = KEY2_GPIO_PIN;
    //设置按键的引脚为浮空输入
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    //使用结构体初始化按键
    GPIO_Init(KEY2_GPIO_PORT, &GPIO_InitStructure);
    

    }

    /** 按键按下标置宏

    • 按键按下为高电平,设置 KEY_ON=1, KEY_OFF=0
    • 若按键按下为低电平,把宏设置成 KEY_ON=0 ,KEY_OFF=1 即可
      /
      #define KEY_ON 1
      #define KEY_OFF 0
      /
      *
    • @brief 检测是否有按键按下
    • @param GPIOx:具体的端口, x 可以是(A...G)
    • @param GPIO_PIN:具体的端口位, 可以是 GPIO_PIN_x(x 可以是 0...15)
    • @retval 按键的状态
    • @arg KEY_ON:按键按下
      
    • @arg KEY_OFF:按键没按下
      

    */

    uint8_t Key_Scan(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin){
    /*检测是否有按键按下 */
    if (GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) == KEY_ON){
    /*等待按键释放 */
    while (GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) == KEY_ON);
    return KEY_ON;
    }
    else return KEY_OFF;
    }

    main.c

    #include <stm32f10x.h>
    #include "button.h"
    #include "led.h"

    /**

    • @brief 主函数

    • @param 无

    • @retval 无
      /
      int main(void){
      /
      LED 端口初始化 */
      LED_GPIO_Config();
      /初始化按键/
      Key_GPIO_Config();

      /* 轮询按键状态,若按键按下则反转 LED */
      while (1) {
      if ( Key_Scan(KEY1_GPIO_PORT,KEY1_GPIO_PIN) == KEY_ON ) {
      /LED1 反转/
      LED1_TOGGLE;
      }
      if ( Key_Scan(KEY2_GPIO_PORT,KEY2_GPIO_PIN) == KEY_ON ) {
      /LED2 反转/
      LED2_TOGGLE;
      }
      }
      }
      0_1597488278984_2f698580-4656-464d-8ea4-6a3f3d8218dd-image.png 0_1597488298152_40eaa55d-9575-456d-9bc3-21e0a81402c0-image.png 0_1597488316106_bb266273-4054-4d83-a3a1-055271e496c2-image.png

    0_1597488338806_cb43dd4a-91eb-45ff-ae54-ba85a340ab78-image.png
    0_1597488356432_bf27db8a-e7cf-44af-8785-0b7563dc71f6-image.png 查询与中断的区别
    查询不需要进入中断设置,只需要对系统定时器进行装载,通过系统定时器的自发倒数进行计时,只要查询定时器是否完成倒数即可
    查询的好处是不会打断单片机工作,提高工作效率,并且查询延时的编写方式易于理解

    代码如下

    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; //清空计数器
    

    }

    大致流程为:
    1.先设置计时器LOAD值,确定计时器从多少开始倒计时
    2.清空计数器并使能,开始倒计时
    3.不断查询,直到倒计时完成
    4.关闭并清空计数器

        计时器倒数一个数字的时间是1/SYSCLK,所以,1ms就应该是倒数了SYSCLK/1000个数字
    

    0_1597488393774_7ab67e8d-40d3-48c7-b796-a7285e106ae6-image.png
    先对所有引脚进行定义与初始化

    #ifndef __DIGITAL_H
    #define __DIGITAL_H

    #include <stm32f10x.h>

    //1--e
    //2--a
    //3--d
    //4--f
    //5--h
    //6--b
    //7--c
    //8--g

    #define Digital1_GPIO_PORT GPIOB
    #define Digital1_GPIO_CLK RCC_APB2Periph_GPIOB
    #define Digital1_GPIO_PIN GPIO_Pin_12

    #define Digital2_GPIO_PORT GPIOB
    #define Digital2_GPIO_CLK RCC_APB2Periph_GPIOB
    #define Digital2_GPIO_PIN GPIO_Pin_13

    #define Digital3_GPIO_PORT GPIOB
    #define Digital3_GPIO_CLK RCC_APB2Periph_GPIOB
    #define Digital3_GPIO_PIN GPIO_Pin_14

    #define Digital4_GPIO_PORT GPIOB
    #define Digital4_GPIO_CLK RCC_APB2Periph_GPIOB
    #define Digital4_GPIO_PIN GPIO_Pin_15

    #define Digital5_GPIO_PORT GPIOC
    #define Digital5_GPIO_CLK RCC_APB2Periph_GPIOC
    #define Digital5_GPIO_PIN GPIO_Pin_6

    #define Digital6_GPIO_PORT GPIOC
    #define Digital6_GPIO_CLK RCC_APB2Periph_GPIOC
    #define Digital6_GPIO_PIN GPIO_Pin_7

    #define Digital7_GPIO_PORT GPIOB
    #define Digital7_GPIO_CLK RCC_APB2Periph_GPIOB
    #define Digital7_GPIO_PIN GPIO_Pin_8

    #define Digital8_GPIO_PORT GPIOB
    #define Digital8_GPIO_CLK RCC_APB2Periph_GPIOB
    #define Digital8_GPIO_PIN GPIO_Pin_9

    #define int1_GPIO_PORT GPIOB
    #define int1_GPIO_CLK RCC_APB2Periph_GPIOB
    #define int1_GPIO_PIN GPIO_Pin_6

    #define int2_GPIO_PORT GPIOB
    #define int2_GPIO_CLK RCC_APB2Periph_GPIOB
    #define int2_GPIO_PIN GPIO_Pin_7

    #define int3_GPIO_PORT GPIOA
    #define int3_GPIO_CLK RCC_APB2Periph_GPIOA
    #define int3_GPIO_PIN GPIO_Pin_2

    #define int4_GPIO_PORT GPIOA
    #define int4_GPIO_CLK RCC_APB2Periph_GPIOA
    #define int4_GPIO_PIN GPIO_Pin_11

    /* 直接操作寄存器的方法控制 IO /
    #define digitalHi(p,i) {p->BSRR=i;} //输出为高电平
    #define digitalLo(p,i) {p->BRR=i;} //输出低电平
    #define digitalToggle(p,i) {p->ODR ^=i;} //输出反转状态
    /
    定义控制 IO 的宏 */
    #define Digital1_TOGGLE digitalToggle(Digital1_GPIO_PORT,Digital1_GPIO_PIN)
    #define Digital1_OFF digitalHi(Digital1_GPIO_PORT,Digital1_GPIO_PIN)
    #define Digital1_ON digitalLo(Digital1_GPIO_PORT,Digital1_GPIO_PIN)

    #define Digital2_TOGGLE digitalToggle(Digital2_GPIO_PORT,Digital2_GPIO_PIN)
    #define Digital2_OFF digitalHi(Digital2_GPIO_PORT,Digital2_GPIO_PIN)
    #define Digital2_ON digitalLo(Digital2_GPIO_PORT,Digital2_GPIO_PIN)

    #define Digital3_TOGGLE digitalToggle(Digital3_GPIO_PORT,Digital3_GPIO_PIN)
    #define Digital3_OFF digitalHi(Digital3_GPIO_PORT,Digital3_GPIO_PIN)
    #define Digital3_ON digitalLo(Digital3_GPIO_PORT,Digital3_GPIO_PIN)

    #define Digital4_TOGGLE digitalToggle(Digital4_GPIO_PORT,Digital4_GPIO_PIN)
    #define Digital4_OFF digitalHi(Digital4_GPIO_PORT,Digital4_GPIO_PIN)
    #define Digital4_ON digitalLo(Digital4_GPIO_PORT,Digital4_GPIO_PIN)

    #define Digital5_TOGGLE digitalToggle(Digital5_GPIO_PORT,Digital5_GPIO_PIN)
    #define Digital5_OFF digitalHi(Digital5_GPIO_PORT,Digital5_GPIO_PIN)
    #define Digital5_ON digitalLo(Digital5_GPIO_PORT,Digital5_GPIO_PIN)

    #define Digital6_TOGGLE digitalToggle(Digital6_GPIO_PORT,Digital6_GPIO_PIN)
    #define Digital6_OFF digitalHi(Digital6_GPIO_PORT,Digital6_GPIO_PIN)
    #define Digital6_ON digitalLo(Digital6_GPIO_PORT,Digital6_GPIO_PIN)

    #define Digital7_TOGGLE digitalToggle(Digital7_GPIO_PORT,Digital7_GPIO_PIN)
    #define Digital7_OFF digitalHi(Digital7_GPIO_PORT,Digital7_GPIO_PIN)
    #define Digital7_ON digitalLo(Digital7_GPIO_PORT,Digital7_GPIO_PIN)

    #define Digital8_TOGGLE digitalToggle(Digital8_GPIO_PORT,Digital8_GPIO_PIN)
    #define Digital8_OFF digitalHi(Digital8_GPIO_PORT,Digital8_GPIO_PIN)
    #define Digital8_ON digitalLo(Digital8_GPIO_PORT,Digital8_GPIO_PIN)

    #define int1_TOGGLE digitalToggle(int1_GPIO_PORT,int1_GPIO_PIN)
    #define int1_OFF digitalHi(int1_GPIO_PORT,int1_GPIO_PIN)
    #define int1_ON digitalLo(int1_GPIO_PORT,int1_GPIO_PIN)

    #define int2_TOGGLE digitalToggle(int2_GPIO_PORT,int2_GPIO_PIN)
    #define int2_OFF digitalHi(int2_GPIO_PORT,int2_GPIO_PIN)
    #define int2_ON digitalLo(int2_GPIO_PORT,int2_GPIO_PIN)

    #define int3_TOGGLE digitalToggle(int3_GPIO_PORT,int3_GPIO_PIN)
    #define int3_OFF digitalHi(int3_GPIO_PORT,int3_GPIO_PIN)
    #define int3_ON digitalLo(int3_GPIO_PORT,int3_GPIO_PIN)

    #define int4_TOGGLE digitalToggle(int4_GPIO_PORT,int4_GPIO_PIN)
    #define int4_OFF digitalHi(int4_GPIO_PORT,int4_GPIO_PIN)
    #define int4_ON digitalLo(int4_GPIO_PORT,int4_GPIO_PIN)

    //one--b,c--6,7
    #define one_
    Digital1_ON;
    Digital2_ON
    Digital3_ON
    Digital4_ON
    Digital5_ON
    Digital6_OFF
    Digital7_OFF
    Digital8_ON

    //two--a,b,d,e,g--1,2,3,6,8
    #define two_
    Digital1_OFF;
    Digital2_OFF
    Digital3_OFF
    Digital4_ON
    Digital5_ON
    Digital6_OFF
    Digital7_ON
    Digital8_OFF

    //three--a,b,c,d,g--2,3,6,7,8
    #define three_
    Digital1_ON;
    Digital2_OFF
    Digital3_OFF
    Digital4_ON
    Digital5_ON
    Digital6_OFF
    Digital7_OFF
    Digital8_OFF

    //four--b,c,f,g--4,6,7,8
    #define four_
    Digital1_ON;
    Digital2_ON
    Digital3_ON
    Digital4_OFF
    Digital5_ON
    Digital6_OFF
    Digital7_OFF
    Digital8_OFF

    //five--a,c,d,f,g--2,3,4,7,8
    #define five_
    Digital1_ON;
    Digital2_OFF
    Digital3_OFF
    Digital4_OFF
    Digital5_ON
    Digital6_ON
    Digital7_OFF
    Digital8_OFF

    //six--a,c,d,e,f,g--1,2,3,4,7,8
    #define six_
    Digital1_OFF;
    Digital2_OFF
    Digital3_OFF
    Digital4_OFF
    Digital5_ON
    Digital6_ON
    Digital7_OFF
    Digital8_OFF

    //seven--a,b,c--2,6,7
    #define seven_
    Digital1_ON;
    Digital2_OFF
    Digital3_ON
    Digital4_ON
    Digital5_ON
    Digital6_OFF
    Digital7_OFF
    Digital8_ON

    //eight--a,b,c,d,e,f,g--1,2,3,4,6,7,8
    #define eight_
    Digital1_OFF;
    Digital2_OFF
    Digital3_OFF
    Digital4_OFF
    Digital5_ON
    Digital6_OFF
    Digital7_OFF
    Digital8_OFF

    //nine--a,b,c,d,f,g--2,3,4,6,7,8
    #define nine_
    Digital1_ON;
    Digital2_OFF
    Digital3_OFF
    Digital4_OFF
    Digital5_ON
    Digital6_OFF
    Digital7_OFF
    Digital8_OFF

    //zero--a,b,c,d,e,f--1,2,3,4,6,7
    #define zero_
    Digital1_OFF;
    Digital2_OFF
    Digital3_OFF
    Digital4_OFF
    Digital5_ON
    Digital6_OFF
    Digital7_OFF
    Digital8_ON

    //dark--
    #define dark_
    int1_OFF;
    int2_OFF
    int3_OFF
    int4_OFF

    //LED1
    #define INT1_
    int1_ON;
    int2_OFF
    int3_OFF
    int4_OFF

    //LED2
    #define INT2_
    int1_OFF;
    int2_ON
    int3_OFF
    int4_OFF

    //LED3
    #define INT3_
    int1_OFF;
    int2_OFF
    int3_ON
    int4_OFF

    //LED4
    #define INT4_
    int1_OFF;
    int2_OFF
    int3_OFF
    int4_ON

    void Digital_GPIO_Config(void){
    /定义一个 GPIO_InitTypeDef 类型的结构体/
    GPIO_InitTypeDef GPIO_InitStructure;
    /开启 LED 相关的 GPIO 外设时钟/
    RCC_APB2PeriphClockCmd( Digital1_GPIO_CLK|Digital2_GPIO_CLK|Digital3_GPIO_CLK|Digital4_GPIO_CLK|
    Digital5_GPIO_CLK|Digital6_GPIO_CLK|Digital7_GPIO_CLK|Digital8_GPIO_CLK|
    int1_GPIO_PIN|int2_GPIO_PIN|int3_GPIO_PIN|int4_GPIO_PIN, ENABLE);

    /*选择要控制的 GPIO 引脚*/
    GPIO_InitStructure.GPIO_Pin = Digital1_GPIO_PIN;
    /*设置引脚模式为通用推挽输出*/
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    /*设置引脚速率为 50MHz */
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    /*调用库函数,初始化 GPIO*/
    GPIO_Init(Digital1_GPIO_PORT, &GPIO_InitStructure);
    
    
    /*选择要控制的 GPIO 引脚*/
    GPIO_InitStructure.GPIO_Pin = Digital2_GPIO_PIN;
    

    /调用库函数,初始化 GPIO/
    GPIO_Init(Digital2_GPIO_PORT, &GPIO_InitStructure);

    /*选择要控制的 GPIO 引脚*/
    GPIO_InitStructure.GPIO_Pin = Digital3_GPIO_PIN;
    

    /调用库函数,初始化 GPIO/
    GPIO_Init(Digital3_GPIO_PORT, &GPIO_InitStructure);

    /*选择要控制的 GPIO 引脚*/
    GPIO_InitStructure.GPIO_Pin = Digital4_GPIO_PIN;
    

    /调用库函数,初始化 GPIO/
    GPIO_Init(Digital4_GPIO_PORT, &GPIO_InitStructure);

    /*选择要控制的 GPIO 引脚*/
    GPIO_InitStructure.GPIO_Pin = Digital5_GPIO_PIN;
    

    /调用库函数,初始化 GPIO/
    GPIO_Init(Digital5_GPIO_PORT, &GPIO_InitStructure);

    /*选择要控制的 GPIO 引脚*/
    GPIO_InitStructure.GPIO_Pin = Digital6_GPIO_PIN;
    

    /调用库函数,初始化 GPIO/
    GPIO_Init(Digital6_GPIO_PORT, &GPIO_InitStructure);

    /*选择要控制的 GPIO 引脚*/
    GPIO_InitStructure.GPIO_Pin = Digital7_GPIO_PIN;
    

    /调用库函数,初始化 GPIO/
    GPIO_Init(Digital7_GPIO_PORT, &GPIO_InitStructure);

    /*选择要控制的 GPIO 引脚*/
    GPIO_InitStructure.GPIO_Pin = Digital8_GPIO_PIN;
    

    /调用库函数,初始化 GPIO/
    GPIO_Init(Digital8_GPIO_PORT, &GPIO_InitStructure);

    /*选择要控制的 GPIO 引脚*/
    GPIO_InitStructure.GPIO_Pin = int1_GPIO_PIN;
    

    /调用库函数,初始化 GPIO/
    GPIO_Init(int1_GPIO_PORT, &GPIO_InitStructure);

    /*选择要控制的 GPIO 引脚*/
    GPIO_InitStructure.GPIO_Pin = int2_GPIO_PIN;
    

    /调用库函数,初始化 GPIO/
    GPIO_Init(int2_GPIO_PORT, &GPIO_InitStructure);

    /*选择要控制的 GPIO 引脚*/
    GPIO_InitStructure.GPIO_Pin = int3_GPIO_PIN;
    

    /调用库函数,初始化 GPIO/
    GPIO_Init(int3_GPIO_PORT, &GPIO_InitStructure);

    /*选择要控制的 GPIO 引脚*/
    GPIO_InitStructure.GPIO_Pin = int4_GPIO_PIN;
    

    /调用库函数,初始化 GPIO/
    GPIO_Init(int4_GPIO_PORT, &GPIO_InitStructure);

    }

    #endif

    main.c

    #include <stm32f10x.h>
    #include "delay.h"
    #include "led.h"
    #include "Digital_Tube.h"

    void display(int m,int n,int i,int j);
    void digital(int m);

    int main(){

    LED_GPIO_Config();
    Digital_GPIO_Config();
    
    for(int m = 0; m < 10; m++){
    	for(int n = 0; n < 10; n++){
    		for(int i = 0; i < 10; i++){
    			for(int j = 0; j < 10; j++){
    				for(int z = 0; z < 50; z++){
    					display(m,n,i,j);
    				}
    			}
    		}
    	}
    }
    

    }

    void display(int m,int n,int i,int j){
    INT1_;
    digital(m);
    delay_ms(5);

    INT2_;
    digital(n);
    delay_ms(5);
    
    INT3_;
    digital(i);
    delay_ms(5);
    
    INT4_;
    digital(j);
    delay_ms(5);
    

    }

    void digital(int m){
    switch(m){
    case 0:
    zero_;
    break;
    case 1:
    one_;
    break;
    case 2:
    two_;
    break;
    case 3:
    three_;
    break;
    case 4:
    four_;
    break;
    case 5:
    five_;
    break;
    case 6:
    six_;
    break;
    case 7:
    seven_;
    break;
    case 8:
    eight_;
    break;
    case 9:
    nine_;
    break;
    default:
    LED1_ON;
    }
    }

        动态显示的原理即为人眼的视觉暂留,人眼一秒可以接收24帧图像,因此,只要闪动的频率高于24Hz(实际值高于24Hz,否则依然会察觉到频闪),人眼就会错认为图像是连续的,在这里,我采用的闪动频率是50Hz,之前的实验表明,50Hz依然有时能察觉到闪烁,但60Hz表现很好。
        根据四位数码管的显示原理,通过控制数码管,先显示第一个数字,再显示第二个,第三个,第四个,然后回到第一个,整个周期为0.02s,观察到逐渐上升的数字,每一秒,数字就加一(利用了之前编写的延时函数)
    

    0_1597488503740_fb08d4c5-5829-4a41-a5a2-6e530bb1bdc5-image.png


  • 核心层

    0_1599896287701_75cded8d-16b1-4269-8025-ef8c6681d9b3-image.png
    对于这一处的说法我不是很理解。对于查询来说,他要不断地去查询相应的寄存器,但如果是中断,我可以不管他的计数,直到中断的产生,中断产生之后的操作和定时器查询完成之后要做的操作应该是大同小异的。这么看的话,中断可以把查询的时间节省出来去做其他的事情,效率更高才对



  • @liangfs 效率这方面,觉得还是学长说的对,之前对中断的理解还不够


 

Copyright © 2018 bbs.dian.org.cn All rights reserved.

与 Dian 的连接断开,我们正在尝试重连,请耐心等待