一、学习CH04示例程序,包括gpio.c和main.c。
二、给出 gpio_set(LIGHT_RED,LIGHT_OFF);语句中,LIGHT_RED和LIGHT_OFF的值是多少?贴出每一步的查找截图。
打开CH04中的GPIO-BlueLight_20230328/07_AppPrg/main.c,找到gpio_set(LIGHT_RED,LIGHT_OFF),选中LIGHT_RED,右键选择查看定义。
跳转到user.h,可以看到LIGHT_RED的值为(PTB_NUM|7),选中PTB_NUM,右键选择查看定义
跳转到gpio.h,看到PTB_NUM的值为(1<<8)也就是256,故LIGHT_RED的值(PTB_NUM|7)为263
在user.h中可以看到LIGHT_OFF的值为1
三、用直接地址编程方式,实现红绿蓝三灯轮流闪烁。
在GPIO-Output-DirectAddress_STM32L431_20200928的main.c的基础上修改
1、将灯状态标志初始化为:‘B’
2、定义B口7、8、9脚为输出引脚
3、主循环部分
完成以上修改即可实现红绿蓝三灯轮流闪烁,
开发板亮灯情况展示
红绿蓝三灯轮流闪烁
源码
//====================================================================
//文件名称:main.c(应用工程主函数)
//框架提供:SD-Arm(sumcu.suda.edu.cn)
//版本更新:2017.08, 2020.05
//功能描述:见本工程的<01_Doc>文件夹下Readme.txt文件
//====================================================================
#define GLOBLE_VAR
#include "includes.h" //包含总头文件
//----------------------------------------------------------------------
//声明使用到的内部函数
//main.c使用的内部函数声明处
//----------------------------------------------------------------------
//主函数,一般情况下可以认为程序从此开始运行(实际上有启动过程见书稿)
int main(void)
{
//(1)======启动部分(开头)==========================================
//(1.1)声明main函数使用的局部变量
uint32_t mMainLoopCount; //主循环使用的记录主循环次数变量
uint8_t mFlag; //主循环使用的临时变量
//(1.2)【不变】关总中断
DISABLE_INTERRUPTS;
//(1.3)给主函数使用的局部变量赋初值
mMainLoopCount = 0; //主循环使用的记录主循环次数变量
mFlag='B'; //主循环使用的临时变量:灯状态标志
//(1.4)给全局变量赋初值
//(1.5)用户外设模块初始化
// B口7、8、9脚(三色全暗,高电平)
//(1.5.1)声明变量
volatile uint32_t* RCC_AHB2; //GPIO的B口时钟使能寄存器地址
volatile uint32_t* gpio_ptr; //GPIO的B口基地址
volatile uint32_t* gpio_mode; //引脚模式寄存器地址=口基地址
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.2)定义B口7、8、9脚为输出引脚方法如下:
*gpio_mode &= ~(0b111111<<14); //0b11111111111100000011111111111111;清零
*gpio_mode |=(1<<14); //0b00000000000000000100000000000000;
*gpio_mode |=(1<<16); //0b00000000000000010000000000000000;
*gpio_mode |=(1<<18); //0b00000000000001000000000000000000;
// (1.5.4)初始化三色小灯全暗
*gpio_bsrr &=(7<<7);
//(1.6)使能模块中断
//(1.7)【不变】开总中断
ENABLE_INTERRUPTS;
printf("-----------------------------------------------------\r\n");
printf("金葫芦提示:直接地址方式进行GPIO输出\r\n");
printf(" 这个编程有点难以看懂,使用构件编程就简单多了,\r\n");
printf(" 但是构件制作要经过这一关,因此,我们把构件制作与\r\n");
printf(" 基于构件的编程分成不同过程。学习嵌入式系统,\r\n");
printf(" 以理解GPIO、UART、定时器、Flash、ADC、...\r\n");
printf(" 知识要素为出发点,学会正确运用构件进行应用编程,\r\n");
printf(" 理解和掌握2~3个简单构件的制作方法即可。\r\n");
printf(" gzhu lfd制作\r\n");
printf("----------------------------------------------------\r\n");
//(1)======启动部分(结尾)==========================================
//(2)======主循环部分(开头)=========================================
for(;;) //for(;;)(开头)
{
//(2.1)主循环次数+1,并判断是否小于特定常数
mMainLoopCount++; //+1
if (mMainLoopCount<=6556677) continue; //如果小于特定常数,继续循环
//(2.2)主循环次数超过特定常数,灯状态进行切换(这样灯会闪烁)
mMainLoopCount=0; //清主循环次数
//切换灯状态
if (mFlag=='B') //若灯状态标志为'R'
{
*gpio_bsrr|=(1<<9); //设置蓝灯“灭”
*gpio_brr|=(1<<7); //设置红灯“亮”
printf("红灯:亮\r\n"); //通过调试串口输出灯的状态
mFlag='R'; //改变状态标志
}
else if (mFlag=='R') //若灯状态标志为'G'
{
*gpio_bsrr|=(1<<7); //设置红灯“灭”
*gpio_brr|=(1<<8); //设置绿灯“亮”
printf("绿灯:亮\r\n"); //通过调试串口输出灯的状态
mFlag='G'; //改变状态标志
}
else if (mFlag=='G') //若灯状态标志为'B'
{
*gpio_bsrr|=(1<<8); //设置绿灯“灭”
*gpio_brr|=(1<<9); //设置蓝灯“亮”
printf("蓝灯:亮\r\n"); //通过调试串口输出灯的状态
mFlag='B'; //改变状态标志
}
} //for(;;)结尾
//(2)======主循环部分(结尾)========================================
}
/*
注① 这样做的目的在于更改了D19、D18两位的值,而不改变其他位的值,不这样的话,
可能把不需要改变的位也改变了!
*/
//======以下为主函数调用的子函数存放处=====================================
//======以下为主函数调用的子函数===========================================
//========================================================================
/*
知识要素:
(1)main.c是一个模板,该文件所有代码均不涉及具体的硬件和环境,通过调用构件
实现对硬件的干预。
(2)本文件中对宏GLOBLE_VAR进行了定义,所以在包含"includes.h"头文件时,会定
义全局变量,在其他文件中包含"includes.h"头文件时,
编译时会自动增加extern
*/
四、用调用构件方式,实现红绿蓝的八种组合轮流闪烁。
在GPIO-Output-Component_STM32L431_20200928的main.c的基础上修改
1、用户外设模块初始化
2、主循环
完成上面的修改后可以实现小灯按照暗、红、绿、黄、蓝、紫、青、白的顺序交替变换
开发板亮灯情况展示
小灯按暗、红、绿、黄、蓝、紫、青、白颜色的顺序交替变换
源码
//======================================================================
//文件名称:main.c(应用工程主函数)
//框架提供:SD-Arm(sumcu.suda.edu.cn)
//版本更新:20191108-20200419
//功能描述:见本工程的..\01_Doc\Readme.txt
//移植规则:【固定】
//======================================================================
#define GLOBLE_VAR
#include "includes.h" //包含总头文件
//----------------------------------------------------------------------
//声明使用到的内部函数
//main.c使用的内部函数声明处
//----------------------------------------------------------------------
//主函数,一般情况下可以认为程序从此开始运行(实际上有启动过程,参见书稿)
int main(void)
{
//(1)======启动部分(开头)==========================================
//(1.1)声明main函数使用的局部变量
uint32_t mMainLoopCount; //主循环次数变量
uint32_t mFlag; //灯的状态标志
uint32_t mLightCount; //灯的状态切换次数
//(1.2)【不变】关总中断
DISABLE_INTERRUPTS;
//(1.3)给主函数使用的局部变量赋初值
mMainLoopCount=0; //主循环次数变量
mFlag=0; //灯的状态标志
mLightCount=0; //灯的闪烁次数
//(1.4)给全局变量赋初值
//(1.5)用户外设模块初始化
gpio_init(LIGHT_RED,GPIO_OUTPUT,LIGHT_OFF); //初始化蓝灯
gpio_init(LIGHT_GREEN,GPIO_OUTPUT,LIGHT_OFF); //初始化绿灯
gpio_init(LIGHT_BLUE,GPIO_OUTPUT,LIGHT_OFF); //初始化蓝灯
//(1.6)使能模块中断
//(1.7)【不变】开总中断
ENABLE_INTERRUPTS;
printf("------------------------------------------------------\n");
printf("金葫芦提示:构件法输出控制小灯亮暗 \n");
printf(" 第一次用构件方法点亮的蓝色发光二极管,\n");
printf(" 这是进行应用编程的第一步,可以在此基础上,\n");
printf(" “照葫芦画瓢”地继续学习实践。\n");
printf(" 例如:改为绿灯;调整闪烁频率等。\n");
printf(" gzhu lfd 制作\n");
printf("------------------------------------------------------\n");
//asm ("bl .");
//for(;;) { } //在此打桩,理解蓝色发光二极管为何亮起来了?
//(1)======启动部分(结尾)==========================================
//(2)======主循环部分(开头)========================================
for(;;) //for(;;)(开头)
{
//(2.1)主循环次数变量+1
mMainLoopCount++;
//(2.2)未达到主循环次数设定值,继续循环
if (mMainLoopCount<=12888999) continue;
//(2.3)达到主循环次数设定值,执行下列语句,进行灯的亮暗处理
//(2.3.1)清除循环次数变量
mMainLoopCount=0;
printf("\n灯的闪烁次数 mLightCount = %d\n",mLightCount);
mFlag=mLightCount % 8; //计算当前小灯要显示的颜色
if(mFlag == 0)
printf("暗\n");
else if(mFlag == 1)
printf("红\n");
else if(mFlag == 2)
printf("绿\n");
else if(mFlag == 3)
printf("黄\n");
else if(mFlag == 4)
printf("蓝\n");
else if(mFlag == 5)
printf("紫\n");
else if(mFlag == 6)
printf("青\n");
else if(mFlag == 7)
printf("白\n");
//重置串口输出灯
gpio_set(LIGHT_RED,LIGHT_OFF);
gpio_set(LIGHT_GREEN,LIGHT_OFF);
gpio_set(LIGHT_BLUE,LIGHT_OFF);
if(mFlag == 1 || mFlag == 3 || mFlag == 5 || mFlag == 7)
{
gpio_set(LIGHT_RED,LIGHT_ON); //红灯“亮”
printf(" LIGHT_RED:ON--\n"); //串口输出灯的状态
}
if(mFlag == 2 || mFlag == 3 || mFlag == 6 || mFlag == 7)
{
gpio_set(LIGHT_GREEN,LIGHT_ON); //绿灯“亮”
printf(" LIGHT_GREEN:ON--\n"); //串口输出灯的状态
}
if(mFlag == 4 || mFlag == 5 || mFlag == 6 || mFlag == 7)
{
gpio_set(LIGHT_BLUE,LIGHT_ON); //蓝灯“亮”
printf(" LIGHT_BLUE:ON--\n"); //串口输出灯的状态
}
if(mFlag == 0)
{
gpio_set(LIGHT_RED,LIGHT_OFF); //红灯“暗”
printf(" LIGHT_RED:OFF--\n"); //串口输出灯的状态
gpio_set(LIGHT_GREEN,LIGHT_OFF); //绿灯“暗”
printf(" LIGHT_GREEN:OFF--\n"); //串口输出灯的状态
gpio_set(LIGHT_BLUE,LIGHT_OFF); //蓝灯“暗”
printf(" LIGHT_BLUE:OFF--\n"); //串口输出灯的状态
}
mLightCount++;
} //for(;;)结尾
//(2)======主循环部分(结尾)========================================
} //main函数(结尾)
//======以下为主函数调用的子函数===========================================
//========================================================================
/*
知识要素:
(1)main.c是一个模板,该文件所有代码均不涉及具体的硬件和环境,通过调用构件
实现对硬件的干预。
(2)本文件中对宏GLOBLE_VAR进行了定义,所以在包含"includes.h"头文件时,会定
义全局变量,在其他文件中包含"includes.h"头文件时,
编译时会自动增加extern
*/