1. LED闪烁的简化代码

STM32F107VC LED 简化代码与文档解析

IV板中的LED例程是通过调用STM32的标准库实现的,通过对例程代码与相关文档的解析

可以简化例程的代码实现相同的功能

说明与步骤如下

STM32F107VC将寄存器影射到内存空间,对内存的读写操作即可实现对寄存器的操作

(STM32F105xx STM32F107xx DataSheet, 4. Memory Map, P30)

实现控制LED的功能需要两部分代码,初始化部分,和信号控制部分

初始化又分为重置时钟控制,RCC,和端口配置 APB2 Port D

重置时钟控制器,Reset & Clock Control是STM32F107VC中的资源配给控制,设置RCC控制器才能使各个端口处于工作状态

根据用户手册,LED使用PortD的输出控制

(神舟IV号用户手册,1.2.17,P42)

所以在RCC控制器中需要对APB2PORTD进行设置

根据编程手册,RCC的偏移地址为0x40021000

(Reference Manual, 2.3, P41)

RCC_APB2RSTR的偏移地址为0x0C

(Reference Manual, 6.3.4, P89)

同时要对AFIO使能,于是得到代码如下

RCC Enable

    volatile unsigned int *rcc_apb2enr;

    volatile unsigned char *rcc;

    rcc = (unsigned char*)0x1000; //rcc base

    rcc += 0x20000; // ahb base

    rcc += 0x40000000; // per base

    rcc_apb2enr = (unsigned int*)(rcc + 0x18);  //apb2enr

    (*rcc_apb2enr) |= (unsigned int)0x21; // rcc_gpiod and rcc_afio

根据GPIOD端口定义,需要把2,3,4,7设置成为Output,并设定动作时钟,偏移地址0x0

(Reference Manual, 8.2.1, P148)

得到代码

GPIO Setup

    volatile unsigned char *gpiod;

    volatile unsigned int *gpiod_ctl;

    unsigned int gpio_ctl_speed;

    unsigned int gpio_ctl_output_n;

 

//GPIO_D init

//LED GPIOD 2, 3, 4, 7

    gpiod = (unsigned char*) 0x1400;

    gpiod += 0x10000; //apb2 base

    gpiod += 0x40000000; //per base;

    gpiod_ctl = (unsigned int*)(gpiod + 0x0);

    gpio_ctl_speed = (unsigned int)0x3; // 50 MHz, 11 (binary)

    gpio_ctl_speed = (gpio_ctl_speed << 8) | (gpio_ctl_speed << 12) | (gpio_ctl_speed << 16) | (gpio_ctl_speed << 28);

    gpio_ctl_output_n = (unsigned int)0xC; //CNF ~00xx (binary)

    gpio_ctl_output_n = (~(gpio_ctl_output_n << 8)) & (~(gpio_ctl_output_n << 12)) & (~(gpio_ctl_output_n << 16)) & (~(gpio_ctl_output_n << 28));

    (*gpiod_ctl) |= gpio_ctl_speed;

    (*gpiod_ctl) &= gpio_ctl_output_n;

对LED的控制需要对GPIO-D的BRR和BSRR写入

BRR写入LED点灯,偏移地址0x14

(Reference Manual, 8.2.6, P151)

BSRR写入LED熄灯

(Reference Manual, 8.2.5, P150)

得到代码

GPIOD Write

void light_led(int num, int dset) {

    unsigned short int led_pin[4];

    volatile unsigned char *gpiod;

    volatile unsigned short int *gpiod_brr;

    volatile unsigned int *gpiod_bsrr;

    unsigned short led_value;

    led_pin[0] = (unsigned short int)(0x1 << 2);

    led_pin[1] = (unsigned short int)(0x1 << 3);

    led_pin[2] = (unsigned short int)(0x1 << 4);

    led_pin[3] = (unsigned short int)(0x1 << 7);

    gpiod = (unsigned char*) 0x1400;

    gpiod += 0x10000; //apb2 base

    gpiod += 0x40000000; //per base;

    gpiod_brr = (unsigned short int*)(gpiod + 0x14);

    gpiod_bsrr = (unsigned int*)(gpiod + 0x10);

    if (dset) {

        led_value = led_pin[num % 4];

        (*gpiod_brr) |= led_value;

    } else {

        led_value = led_pin[num % 4];

        (*gpiod_bsrr) |= led_value;

    }

}

加入控制逻辑,全部代码如下,不再依靠STM32标准库编译

Code

void led_init() {

//RCC init

    volatile unsigned int *rcc_apb2enr;

    volatile unsigned char *rcc;

    volatile unsigned char *gpiod;

    volatile unsigned int *gpiod_ctl;

    unsigned int gpio_ctl_speed;

    unsigned int gpio_ctl_output_n;

   

    rcc = (unsigned char*)0x1000; //rcc base

    rcc += 0x20000; // ahb base

    rcc += 0x40000000; // per base

    rcc_apb2enr = (unsigned int*)(rcc + 0x18);  //apb2enr

    (*rcc_apb2enr) |= (unsigned int)0x21; // rcc_gpiod and rcc_afio

//GPIO_D init

//LED GPIOD 2, 3, 4, 7

    gpiod = (unsigned char*) 0x1400;

    gpiod += 0x10000; //apb2 base

    gpiod += 0x40000000; //per base;

    gpiod_ctl = (unsigned int*)(gpiod + 0x0);

    gpio_ctl_speed = (unsigned int)0x3; // 50 MHz, 11 (binary)

    gpio_ctl_speed = (gpio_ctl_speed << 8) | (gpio_ctl_speed << 12) | (gpio_ctl_speed << 16) | (gpio_ctl_speed << 28);

    gpio_ctl_output_n = (unsigned int)0xC; //CNF ~00xx (binary)

    gpio_ctl_output_n = (~(gpio_ctl_output_n << 8)) & (~(gpio_ctl_output_n << 12)) & (~(gpio_ctl_output_n << 16)) & (~(gpio_ctl_output_n << 28));

    (*gpiod_ctl) |= gpio_ctl_speed;

    (*gpiod_ctl) &= gpio_ctl_output_n;}

void light_led(int num, int dset) {

    unsigned short int led_pin[4];

    volatile unsigned char *gpiod;

    volatile unsigned short int *gpiod_brr;

    volatile unsigned int *gpiod_bsrr;

    unsigned short led_value;

    led_pin[0] = (unsigned short int)(0x1 << 2);

    led_pin[1] = (unsigned short int)(0x1 << 3);

    led_pin[2] = (unsigned short int)(0x1 << 4);

    led_pin[3] = (unsigned short int)(0x1 << 7);

    gpiod = (unsigned char*) 0x1400;

    gpiod += 0x10000; //apb2 base

    gpiod += 0x40000000; //per base;

    gpiod_brr = (unsigned short int*)(gpiod + 0x14);

    gpiod_bsrr = (unsigned int*)(gpiod + 0x10);

    if (dset) {

        led_value = led_pin[num % 4];

        (*gpiod_brr) |= led_value;

    } else {

        led_value = led_pin[num % 4];

        (*gpiod_bsrr) |= led_value;

    }

}

void sleep(int msec) {

    int nsec;

    for (nsec=msec*1000; nsec>0; nsec--);

}

int main() {

    int lnum=0;

    float snum=1;

    float incs=1;

    led_init();

    while (1) {

        light_led(lnum, incs<1?0:1);

        sleep((int)snum);

        light_led(lnum, incs<1?1:0);

        lnum++;

        lnum %= 4;

        snum=incs*snum;

        incs=snum<=1?1.01:(snum>=1000?0.99:incs);

    }

}