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);
}
}