1、学习CH04示例程序,包括gpio.c和4个工程中的main.c

2、给出 gpio set(LIGHT _RED,LIGHT_OFF);语句中LIGHT RED和LIGHT OFF的值是多少?贴出每一步的查找截图
LIGHT_RED 和 LIGHT_OFF在..\CH04\GPIO-Output-Component\05_UserBoard\User.h中定义
可以看到#define LIGHT_RED (PTB_NUM|7) //红灯,(GEC_56)其中PTB_NUM为端口号地址偏移量,在gpio.h可以看到其定义
可得PTB_NUM的值为 0B 1 0000 0000
故LIGHT_RED为0B 1 0000 0111
LIGHT_OFF为0B 0000 0001
3、用直接地址编程方式,实现红绿蓝三灯轮流闪烁
在..\CH04\GPIO-Output-DirectAddress_STM32L431_20200928的工程中的main.c中修改实现
- 设置状态标志mFlag,其中'R'为红色,'G'为绿色,‘B’为蓝色,'L'为灯暗,初始化为R红色
- B端口7、8、9引脚分别代表红、绿、蓝,将以上引脚都设置为01:通用输出模式
- 根据状态标志mFlag的不同,使用gpio_brr复位寄存器,将对应引脚设置为低电平,即点亮该灯
- 当红、绿、蓝三种灯都亮了一轮之后,使用gpio_bsrr将所有引脚都置为高电平,即将所有灯熄灭,此时置mFlag为‘L’,接着继续循环红、绿、蓝、灯暗
#define GLOBLE_VAR
#include "includes.h"
int main(void)
{
//(1)======启动部分(开头)==========================================
//(1.1)声明main函数使用的局部变量
uint32_t mMainLoopCount; //主循环使用的记录主循环次数变量
uint8_t mFlag; //主循环使用的临时变量
//(1.2)【不变】关总中断
DISABLE_INTERRUPTS;
//(1.3)给主函数使用的局部变量赋初值
mMainLoopCount = 0; //主循环使用的记录主循环次数变量
mFlag='R'; //主循环使用的临时变量,'R'红色,'G'绿色,'B'蓝色
//(1.4)给全局变量赋初值
//(1.5)用户外设模块初始化
// B口7脚(红灯,低电平点亮)
// B口8脚(绿灯,低电平点亮)
// B口9脚(蓝灯,低电平点亮)
//(1.5.1)声明变量
volatile uint32_t* RCC_AHB2; //GPIO的B口时钟使能寄存器地址
volatile uint32_t* gpio_ptr; //GPIO的B口基地址
volatile uint32_t* gpio_mode; //引脚模式寄存器地址=口基地址 0x 4800 0400 UL
volatile uint32_t* gpio_bsrr; //置位/复位寄存器地址
volatile uint32_t* gpio_brr; //GPIO位复位寄存器
//(1.5.2)变量赋值
RCC_AHB2=(uint32_t*)0x4002104C; //GPIO的B口时钟使能寄存器地址
gpio_ptr=(uint32_t*)0x48000400; //GPIO的B口基地址
gpio_mode=gpio_ptr; //引脚模式寄存器地址=口基地址
gpio_bsrr=gpio_ptr+6; //置位/复位寄存器地址
gpio_brr=gpio_ptr+10; //GPIO位复位寄存器
//(1.5.3)GPIO初始化
//(1.5.3.1)使能相应GPIOB的时钟
*RCC_AHB2|=(1<<1); //GPIOB的B口时钟使能
// (1.5.3.1)设置 B7、B8、B9 引脚为 01:通用输出模式
// 定义B口7脚为输出引脚(令D15、D14=01)
*gpio_mode &= ~(3<<14); //15,14位 置0
*gpio_mode |=(1<<14); //14位置1
// 定义B口8脚为输出引脚(令D17、D16=01)
*gpio_mode &= ~(3<<16); //16,17位 置0
*gpio_mode |=(1<<16); //16位置1
// 定义B口9脚为输出引脚(令D19、D18=01)
*gpio_mode &= ~(3<<18);
*gpio_mode |=(1<<18);
//(1.6)使能模块中断
//(1.7)【不变】开总中断
ENABLE_INTERRUPTS;
printf("-----------------------------------------------------\r\n");
printf("用直接地址编程方式,实现红绿蓝三灯轮流闪烁\r\n");
printf(" 广州大学--cqh\r\n");
printf("----------------------------------------------------\r\n");
//(1)======启动部分(结尾)==========================================
//(2)======主循环部分(开头)=========================================
for(;;) //for(;;)(开头)
{
//(2.1)主循环次数+1,并判断是否小于特定常数
mMainLoopCount++; //+1
if (mMainLoopCount<=6556677) continue; //如果小于特定常数,继续循环
//(2.2)主循环次数超过特定常数,灯状态进行切换(这样灯会闪烁)
mMainLoopCount=0; //清主循环次数
// 根据当前灯的状态标志切换灯状态
switch (mFlag) {
case 'R':
*gpio_brr |= (1 << 7); //设置红灯亮
printf("红灯:亮\r\n");
mFlag = 'G'; //标志改为绿灯
break;
case 'G':
*gpio_brr |= (1 << 8); //设置绿灯亮
printf("绿灯:亮\r\n");
mFlag = 'B'; //标志改为蓝灯
break;
case 'B': // 蓝灯
*gpio_brr |= (1 << 9); // 点亮蓝灯
printf("蓝灯:亮\r\n");
mFlag = 'L'; // 灭灯
break;
case 'L': // 灭灯
*gpio_bsrr |= ((1 << 7) | (1 << 8) | (1 << 9)); // 设置灯暗
printf("所有灯暗\r\n\n");
mFlag = 'R'; // 切换到红灯 循环
break;
}
}
}
4、用调用构件方式,实现红绿蓝的八种组合轮流闪烁
在..\CH04\GPIO-Output-Component_STM32L431_20200928中修改main.c函数实现
#define GLOBLE_VAR
#include "includes.h" //包含总头文件
//----------------------------------------------------------------------
//声明使用到的内部函数
//main.c使用的内部函数声明处
void Delay_ms(uint16_t u16ms);
//----------------------------------------------------------------------
//主函数,一般情况下可以认为程序从此开始运行(实际上有启动过程,参见书稿)
int main(void)
{
//(1)======启动部分(开头)==========================================
//(1.1)声明main函数使用的局部变量
uint32_t mCount; //延时的次数
//(1.2)【不变】关总中断
DISABLE_INTERRUPTS;
//(1.3)给主函数使用的局部变量赋初值
mCount=0;//记次数
//(1.4)给全局变量赋初值
//(1.5)用户外设模块初始化
gpio_init(LIGHT_BLUE,GPIO_OUTPUT,LIGHT_OFF); //初始化蓝灯
gpio_init(LIGHT_GREEN,GPIO_OUTPUT,LIGHT_OFF); //初始化绿灯
gpio_init(LIGHT_RED,GPIO_OUTPUT,LIGHT_OFF); //初始化红灯
uart_init(UART_User,115200); //初始化串口模块
//(1.6)使能模块中断
uart_enable_re_int(UART_User);
//(1.7)【不变】开总中断
ENABLE_INTERRUPTS;
printf("-----------------------------------------------------\r\n");
printf("用调用构件方式,实现红绿蓝的八种组合轮流闪烁\r\n");
printf(" 广州大学--cqh\r\n");
printf("----------------------------------------------------\r\n");
//(1)======启动部分(结尾)==========================================
//(2)======主循环部分(开头)========================================
//每5秒变换一种颜色,一个循环共40秒
for(;;) //for(;;)(开头)
{
//延时1秒
Delay_ms(1000);
mCount++;
//当秒数40秒时,重新开始计数
//避免一直累加
if (mCount > 40)
{
mCount=1;
}
if(mCount%5==0)
{
gpio_reverse(LIGHT_RED);
printf(" LIGHT_RED:reverse--\n"); //串口输出灯的状态
if(mCount/5==1)
{
printf("指示灯颜色为【红色】\n");
}
else if(mCount/5==3)
{
printf("指示灯颜色为【黄色】\n");
}
else if(mCount/5==5)
{
printf("指示灯颜色为【紫色】\n");
}
else if(mCount/5==7)
{
printf("指示灯颜色为【白色】\n");
}
}
if (mCount%10==0) //判断灯的状态标志
{
gpio_reverse(LIGHT_GREEN);
printf(" LIGHT_GREEN:reverse--\n"); //串口输出灯的状态
if(mCount/10==1)
{
printf("指示灯颜色为【绿色】\n");
}
else if(mCount/10==3)
{
printf("指示灯颜色为【青色】\n");
}
}
if (mCount%20==0) //判断灯的状态标志
{
gpio_reverse(LIGHT_BLUE);
printf(" LIGHT_BLUE:reverse--\n"); //串口输出灯的状态
if(mCount/20==1)
{
printf("指示灯颜色为【蓝色】\n");
}
else if(mCount/20==2)
{
printf("指示灯颜色为【暗色】\n");
}
}
} //for(;;)结尾
//(2)======主循环部分(结尾)========================================
} //main函数(结尾)
//======以下为主函数调用的子函数===========================================
//======================================================================
//函数名称:Delay_ms
//函数返回:无
//参数说明:近似毫秒
//功能概要:延时 - 毫秒级
//======================================================================
void Delay_ms(uint16_t u16ms)
{
for(volatile uint32_t i = 0; i < 8000*u16ms; i++) __asm("NOP");
}