嵌入式技术——第四章

嵌入式第四章作业

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

1、GPIO-ASM-STM32L431-20231129的main.s

功能概要:汇编编程调用GPIO构建控制小灯闪烁(利用printf输出提示信息)

代码思路:

(1)数据段与代码存储段的定义。

(2)开始编写main,在启动主循环前初始化定义外设模块、初始化用户外设模块、初始化串口、使能模块中断、开总中断。

(3)跳过启动部分,直接开始主循环部分,定义循环次数,设置灯状态标志mFlag为L,判断灯的状态标志,分别对mFlag为A和F地情况进行处理,同时管理灯的闪烁次数。

2、GPIO_BLUELIGHT-20230328的main.c

功能概要:按照这个c文件的文件名和注释,它应该说的是要求蓝灯亮来着,但是实际上它实现的功能是让红灯一直亮着

代码思路:

(1)gpio_init(LIGHT_RED,GPIO_OUTPUT,LIGHT_OFF);初始化红灯,将红灯初始化为灭的

(2) gpio_set(LIGHT_RED,LIGHT_ON); 设置红灯使得红灯亮起来了

(3)使用for循环,使得程序一直处于执行状态,红灯一直亮

3、GPIO-Output-Component_STM32L431_20200928的main.c

功能概要:利用api实现蓝灯的亮灭循环

代码思路:

(1)定义主循环次数、灯亮灭标志、灯亮灭次数等变量

(3)gpio_init(LIGHT_BLUE,GPIO_OUTPUT,LIGHT_ON); //初始化蓝灯

(3)主循环部分:如灯状态标志mFlag为’L’,灯的闪烁次数+1并显示,改变灯状态及标志;如灯状态标志mFlag为’A’,改变灯状态及标志。

4、GPIO-Output-DirectAddress_STM32L431_20200928的main.c

功能概要:使用直接地址编程的方式实现蓝灯的亮灭循环

代码思路:

(1)声明b端口寄存器地址、复位寄存器地址等变量并赋值

(2)随后对GPIO进行初始化

(3)设置灯为亮

(4)进入循环亮灭状态

5、gpio.c文件

定义了gpio_get_port_pin、gpio_init、gpio_set、gpio_get、gpio_reverse、gpio_pull、gpio_enable_int等多个自定义函数

二、给出 gpio_set(LIGHT_RED,LIGHT_OFF); 语句中, LIGHT_RED和LIGHT_OFF的值是多少?贴出每一步的查找截图。

1、LIGHT_RED值

(1)在user.h文件中找到了LIGHT_RED由PTB_NUM|7定义
在这里插入图片描述

(2)在gpio.h中找到了PTB_NUM定义为1<<8。
在这里插入图片描述

(3)综上可知LIGHT_RED的值是263

2、LIGHT_OFF的值

在user.h中找到了LIGHT_OFF的值大小为0
在这里插入图片描述

三、用直接地址编程方式,实现红绿蓝三灯轮流闪烁

金葫芦的示例程序中有个让蓝灯亮灭的直接地址编程的例子。我根据那玩意改了改就成了红绿蓝三种颜色的灯交换亮了。

想要蓝灯亮,得看看书上表3-7,那里有蓝灯对应的针脚PTB9,还有绿蓝对应的针脚PTB8和PTB7,于是找到B端口对应的模式寄存器GPIOx_MODER,然后将这三个针脚对应的位都置为01,因为01在模式寄存器的配置中表示通用输出模式,就是让这三个对应三个灯的针脚输出信号。

那么要输出什么信号呢?因为针脚只能输出低电平和高电平,我们在书中的图3-4可以看到这三个灯实际上是发光二极管,从正负极来看要输出低电平才能点亮灯。那么就很明了了,我们只要让针脚输出低电平就可以点亮灯,输出高电平就可以熄灭灯。

那么要如何实现高低电平的输出状态改变呢?在端口还有一个寄存器GPIOx_BSRR,这个寄存器是用来控制引脚输出状态的。这个寄存器是32位的,高16位置和低16位都对应x端口的16个针脚。对于我们指定的B端口有16个针脚,寄存器的高16位对应相应的针脚时如果置为0则表示将此针脚置为低电平;寄存器的低16位对应的针脚如果置为1则表示将此针脚输出置为高电平。

所以想要实现红绿蓝三种灯的交替亮灭

只需要先 *gpio_brr|=(1<<7); 设置针脚输出为低电平,红灯“亮”;再 *gpio_bsrr|=(1<<7); 设置针脚输出为高电平,红灯灭。

然后就是绿灯 *gpio_brr|=(1<<8); 和 *gpio_bsrr|=(1<<8); 绿灯亮灭。

蓝灯gpio_brr|=(1<<9); 和 *gpio_bsrr|=(1<<9); 蓝灯亮灭。

对上面进行无限循环,一直亮灭交替。源代码如下:

#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='A';              //主循环使用的临时变量:蓝灯状态标志
    //(1.4)给全局变量赋初值

    //(1.5)用户外设模块初始化
    // B口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.1)定义B口9脚为输出引脚(令D19、D18=01)方法如下:

    //这里使得B9变为了01,输出模式,亮蓝灯
    *gpio_mode &= ~(3<<18);  //0b11111111111100111111111111111111; 
    *gpio_mode |=(1<<18);    //0b00000000000001000000000000000000;

    //这里使得B8变为了01输出模式,绿灯亮
    *gpio_mode &= ~(3<<16);  //0b11111111111111001111111111111111; 
    *gpio_mode |=(1<<16);    //0b00000000000000010000000000000000;

    //这里使得B7变为了01输出模式,红灯亮
    *gpio_mode &= ~(3<<14);  //0b11111111111111110011111111111111; 
    *gpio_mode |=(1<<14);    //0b00000000000000000100000000000000;

    //(思考:为什么这样赋值?答案见本文件末尾注①)

    //(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("----------------------------------------------------\r\n"); 



//(1)======启动部分(结尾)==========================================

//(2)======主循环部分(开头)=========================================
        for(;;)     //for(;;)(开头)
        {

            //(2.1)主循环次数+1,并判断是否小于特定常数
            mMainLoopCount++;                         //+1
            if (mMainLoopCount<=6556677)  continue;   //如果小于特定常数,继续循环
            //(2.2)主循环次数超过特定常数,灯状态进行切换(这样灯会闪烁)
            mMainLoopCount=0;      //清主循环次数
        //红灯
            //切换灯状态
            *gpio_brr|=(1<<7);     //设置灯“亮”
            printf("红灯:亮\r\n");  //通过调试串口输出灯的状态

        ​	for(int i=0;i<10000000;i++)
        ​	{}
        ​   *gpio_bsrr|=(1<<7);     //设置灯“暗”
        ​   printf("红灯:暗\r\n");   //通过调试串口输出灯的状态

            for(int i=0;i<10000000;i++)
            {}
        //绿灯
            *gpio_brr|=(1<<8);     //设置灯“亮”
            printf("绿灯:亮\r\n");  //通过调试串口输出灯的状态
            for(int i=0;i<10000000;i++)
            {}
            *gpio_bsrr|=(1<<8);     //设置灯“暗”
            printf("绿灯:暗\r\n");   //通过调试串口输出灯的状态
            for(int i=0;i<10000000;i++)
            {}
        //蓝灯
            *gpio_brr|=(1<<9);     //设置灯“亮”
            printf("蓝灯:亮\r\n");  //通过调试串口输出灯的状态
            for(int i=0;i<10000000;i++)
            {}
            *gpio_bsrr|=(1<<9);     //设置灯“暗”
            printf("蓝灯:暗\r\n");   //通过调试串口输出灯的状态
            for(int i=0;i<10000000;i++)
            {}
        }     //for(;;)结尾
    //(2)======主循环部分(结尾)========================================
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值