1、学习CH04示例程序,包括gpio.c和4个工程中的main.c.
2、给出gpio_set(LIGHT_RED,LIGHT_OFF);语句中,LIGHT_RED和LiGHT_OFF的值是多少?
1.在user.h中,可以看到:
LIGHT_RED也就是红灯的值为(PTB_NUM|7 );
LiGHT_OFF也就是灯状态为暗的值为1
2.对红灯的值(PTB_NUM|7 )进行寻求具体结果,首先需要知道PTB_NUM宏的定义:
可以看出这个宏的定义是将1左移8位,也就是将1的二进制表示向左移动8位,得到的结果是256;
3.由此进行如下计算:
LIGHT_RED = PTB_NUM | 7
= 0000000100000000 | 0000000000000111
= 0000000100000111
因此,LIGHT_RED
的值为263,其二进制表示为 0000000100000111
3、用直接地址编程方式,实现红绿蓝三灯轮流闪烁
代码:
#include "includes.h"
#define RCC_AHB2_GPIOB_ENABLE (1 << 1)
#define GPIOB_BASE_ADDR 0x48000400
#define GPIO_MODER_OFFSET 0x00
#define GPIO_BSRR_OFFSET 0x18
#define RED_LED_PIN 7
#define GREEN_LED_PIN 8
#define BLUE_LED_PIN 9
#define GPIO_MODE_OUTPUT(pin) (1 << (2 * pin))
#define GPIO_BSRR_SET(pin) (1 << pin)
#define GPIO_BSRR_RESET(pin) (1 << (pin + 16))
void delay(uint32_t milliseconds) {
volatile uint32_t i, j;
for (i = 0; i < milliseconds; ++i) {
for (j = 0; j < 6000; ++j) {}
}
}
int main(void) {
volatile uint32_t* RCC_AHB2 = (uint32_t*)0x4002104C;
volatile uint32_t* GPIOB_MODER = (uint32_t*)0x48000400;
volatile uint32_t* GPIOB_BSRR = (uint32_t*)0x48000418;
*RCC_AHB2 |= RCC_AHB2_GPIOB_ENABLE;
*GPIOB_MODER &= ~((3 << (2 * RED_LED_PIN)) | (3 << (2 * GREEN_LED_PIN)) | (3 << (2 * BLUE_LED_PIN)));
*GPIOB_MODER |= (GPIO_MODE_OUTPUT(RED_LED_PIN) | GPIO_MODE_OUTPUT(GREEN_LED_PIN) | GPIO_MODE_OUTPUT(BLUE_LED_PIN));
while(1) {
// 红灯亮,绿、蓝灯灭
*GPIOB_BSRR = GPIO_BSRR_SET(RED_LED_PIN);
printf("LJF-红灯\n");
delay(1000);
*GPIOB_BSRR = GPIO_BSRR_RESET(RED_LED_PIN);
// 绿灯亮,红、蓝灯灭
*GPIOB_BSRR = GPIO_BSRR_SET(GREEN_LED_PIN);
printf("LJF-绿灯\n");
delay(1000);
*GPIOB_BSRR = GPIO_BSRR_RESET(GREEN_LED_PIN);
// 蓝灯亮,红、绿灯灭
*GPIOB_BSRR = GPIO_BSRR_SET(BLUE_LED_PIN);
printf("LJF-蓝灯\n");
delay(1000);
*GPIOB_BSRR = GPIO_BSRR_RESET(BLUE_LED_PIN);
}
return 0;
}
- 在界面显示如下:
- 开发板中可以看到蓝、红、绿三个颜色交替闪烁
实验分析:
首先,在 main 函数中,通过写入相应的值来启用 GPIOB 时钟,以及设置相应引脚的模式为输出模式。
进入 while(1) 循环后,依次点亮红、绿、蓝三种颜色的 LED 灯,并在每次点亮时打印相应的消息。然后通过延迟函数 delay(1000) 延迟 1000 毫秒(即1秒)。
点亮完一种颜色的 LED 灯后,通过写入相应的值来将该 LED 灯熄灭。
循环执行上述步骤,实现了红、绿、蓝三种颜色的 LED 灯轮流闪烁。
- 实验错误分析:在实验中,出现了将灯光闪烁时间设置过短,导致三个颜色无法分辨其闪烁变化的情况:
4、用调用构建方式,实现红绿蓝的八种组合轮流闪烁
代码:
#include "includes.h"
#define RCC_AHB2_GPIOB_ENABLE (1 << 1)
#define GPIOB_BASE_ADDR 0x48000400
#define GPIO_MODER_OFFSET 0x00
#define GPIO_BSRR_OFFSET 0x18
#define RED_LED_PIN 7
#define GREEN_LED_PIN 8
#define BLUE_LED_PIN 9
#define GPIO_MODE_OUTPUT(pin) (1 << (2 * pin))
#define GPIO_BSRR_SET(pin) (1 << pin)
#define GPIO_BSRR_RESET(pin) (1 << (pin + 16))
void delay(uint32_t milliseconds) {
volatile uint32_t i, j;
for (i = 0; i < milliseconds; ++i) {
for (j = 0; j < 6000; ++j) {}
}
}
void print_message(const char *message) {
printf("%s\n", message);
}
int main(void) {
volatile uint32_t* RCC_AHB2 = (uint32_t*)0x4002104C;
volatile uint32_t* GPIOB_MODER = (uint32_t*)0x48000400;
volatile uint32_t* GPIOB_BSRR = (uint32_t*)0x48000418;
*RCC_AHB2 |= RCC_AHB2_GPIOB_ENABLE;
*GPIOB_MODER &= ~((3 << (2 * RED_LED_PIN)) | (3 << (2 * GREEN_LED_PIN)) | (3 << (2 * BLUE_LED_PIN)));
*GPIOB_MODER |= (GPIO_MODE_OUTPUT(RED_LED_PIN) | GPIO_MODE_OUTPUT(GREEN_LED_PIN) | GPIO_MODE_OUTPUT(BLUE_LED_PIN));
while(1) {
// 1:红灯亮,绿、蓝灯灭
*GPIOB_BSRR = GPIO_BSRR_SET(RED_LED_PIN);
print_message("LJF-红灯");
delay(1000);
*GPIOB_BSRR = GPIO_BSRR_RESET(RED_LED_PIN);
// 2:绿灯亮,红、蓝灯灭
*GPIOB_BSRR = GPIO_BSRR_SET(GREEN_LED_PIN);
print_message("LJF-绿灯");
delay(1000);
*GPIOB_BSRR = GPIO_BSRR_RESET(GREEN_LED_PIN);
// 3:蓝灯亮,红、绿灯灭
*GPIOB_BSRR = GPIO_BSRR_SET(BLUE_LED_PIN);
print_message("LJF-蓝灯");
delay(1000);
*GPIOB_BSRR = GPIO_BSRR_RESET(BLUE_LED_PIN);
// 4:红、绿灯亮,蓝灯灭
*GPIOB_BSRR = GPIO_BSRR_SET(RED_LED_PIN) | GPIO_BSRR_SET(GREEN_LED_PIN);
print_message("LJF-红、绿灯");
delay(1000);
*GPIOB_BSRR = GPIO_BSRR_RESET(RED_LED_PIN) | GPIO_BSRR_RESET(GREEN_LED_PIN);
// 5:绿、蓝灯亮,红灯灭
*GPIOB_BSRR = GPIO_BSRR_SET(GREEN_LED_PIN) | GPIO_BSRR_SET(BLUE_LED_PIN);
print_message("LJF-绿、蓝灯");
delay(1000);
*GPIOB_BSRR = GPIO_BSRR_RESET(GREEN_LED_PIN) | GPIO_BSRR_RESET(BLUE_LED_PIN);
// 6:红、蓝灯亮,绿灯灭
*GPIOB_BSRR = GPIO_BSRR_SET(RED_LED_PIN) | GPIO_BSRR_SET(BLUE_LED_PIN);
print_message("LJF-红、蓝灯");
delay(1000);
*GPIOB_BSRR = GPIO_BSRR_RESET(RED_LED_PIN) | GPIO_BSRR_RESET(BLUE_LED_PIN);
// 7:所有灯都亮
*GPIOB_BSRR = GPIO_BSRR_SET(RED_LED_PIN) | GPIO_BSRR_SET(GREEN_LED_PIN) | GPIO_BSRR_SET(BLUE_LED_PIN);
print_message("LJF-所有灯都亮");
delay(1000);
// 8:所有灯都暗
*GPIOB_BSRR = GPIO_BSRR_RESET(RED_LED_PIN) | GPIO_BSRR_RESET(GREEN_LED_PIN) | GPIO_BSRR_RESET(BLUE_LED_PIN);
print_message("LJF-所有灯都暗");
delay(1000);
}
return 0;
}
在界面显示如下:
开发板中可以看到蓝、红、绿三个颜色交替闪烁:
主要功能是通过操作寄存器来控制LED的亮灭,实现了三种LED组合的八种不同状态的闪烁。
首先配置GPIOB的MODER寄存器,将对应引脚设置为输出模式。
进入一个无限循环,在循环中依次实现八种不同状态的LED组合:
- 红灯亮,绿、蓝灯灭;
- 绿灯亮,红、蓝灯灭;
- 蓝灯亮,红、绿灯灭;
- 红、绿灯亮,蓝灯灭;
- 绿、蓝灯亮,红灯灭;
- 红、蓝灯亮,绿灯灭;
- 所有灯都亮;
- 所有灯都暗。
每个状态持续一秒钟,通过延时函数实现。
每个状态变化时,通过设置或重置GPIOB的BSRR寄存器的相应位来控制LED的亮灭。