• 第一个ARM程序裸板点灯


    硬件知识LED原理图

    如何点亮一个LED灯

    1. 看原理图,确定控制LED的引脚。
    2. 看主芯片的芯片手册,确定如何设置控制这个引脚。
    3. 写程序。

    LED有插脚封装的、贴片封装的。
    在这里插入图片描述
    它们长得完全不一样,因此我们在原理图中把它们抽象出来。

    点亮LED需要通电源,同时为了保护LED,需要加个电阻减小电流。
    控制LED灯的亮灭,可以手动开关LED,但在电子系统中,不可能让人来控制开关,通过编程,利用芯片的引脚去控制开关。

    在这里插入图片描述
    LED的驱动方式,常见的有4种。

    1. 使用引脚输出3.3V点亮LED,输出0V熄灭LED。
    2. 使用引脚拉低到0V点亮LED,输出3.3V熄灭LED。

    有的芯片为了省电等原因,其引脚驱动能力不足,这时可以使用三极管驱动。

    1. 使用引脚输出1.2V点亮LED,输出0V熄灭LED。
    2. 使用引脚输出0V点亮LED,输出1.2V熄灭LED。

    在这里插入图片描述
    由此,主芯片引脚输出高电平/低电平,即可改变LED状态,而无需关注GPIO引脚输出的是3.3V还是1.2V。
    所以简称输出1或0:
    逻辑1–>高电平
    逻辑0–>低电平

    GPIO引脚操作方法

    GPIO:General-purpose input/output,通用输入/输出口。

    GPIO模块一般结构:

    1. 有多组GPIO,每组有多个GPIO
    2. 使能:电源/时钟
    3. 模式(Mode):引脚可用于GPIO或其它功能
    4. 方向:引脚Mode设置为GPIO时,要继续设置它是输出引脚,还是输入引脚
    5. 数值:对于输出引脚,可以设置寄存器让它输出高、低电平。
      对于输入引脚,可以读取寄存器得到引脚的当前电平。

    GPIO寄存器操作:

    1. 芯片手册一般有相关章节,用来介绍power/clock。可以设置对应寄存器使能某个GPIO模块。有些芯片的GPIO是没有使能开头的,即它总是使能的。
    2. 一个引脚可以用于GPIO、串口或其它功能,有对应的寄存器来选择引脚的功能。
    3. 对于已经设置为GPIO功能的引脚,有方向寄存器用来设置它的方向:输入、输出。
    4. 对于已经设置为GPIO功能的引脚,有数据寄存器用来写、读引脚电平状态。

    操作寄存器,不能影响到其它位

    GPIO寄存器的2种操作方法:

    1. 直接读写:读出、修改对应位、写入。
    //将bit n置为1
    val = data_reg;
    val = val | (1 << n);
    data_reg = val;
    
    //清除bit n
    val = data_reg;
    val &= ~(1<<n);
    data_reg = val;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    1. set-and-clear protocol,set_reg、clr_reg、data_reg三个寄存器对应的是同一个物理寄存器。
    set_reg = (1 << n);
    clr_reg = (1 << n);
    
    • 1
    • 2

    STM32F103的LED操作方法

    打开原理图,搜索LED。
    在这里插入图片描述
    在这里插入图片描述
    以PB0为例,它属于GPIOB里的第0个引脚。
    怎么使能GPIOB?
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    将Bit 3设置为1。在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    频率越高,传输数据越快,波形也越陡峭,同时对外界设备的影响也越大。

    在这里插入图片描述
    在这里插入图片描述

    编程

    访问寄存器用指针:

    int a;
    unsigned int*p = &a; //p等于a的地址
    
    *p = val; //写这个地址,就是写a
    val = *p; //读这个地址,就是读a
    
    • 1
    • 2
    • 3
    • 4
    • 5
    unsigned int *p = 0x40010800; //p等于某个寄存器的地址
    *p = val; //写这个地址,就是写这个寄存器
    val = *p; //读寄存器
    
    • 1
    • 2
    • 3
    
    void delay(int d)
    {
        while(d--);
    }
    int main()
    {
        unsigned int *pReg;
        
        /* 使能GPIOB */
        pReg = (unsigned int *)(0x40021000 + 0x18);
        *pReg |= (1<<3);
        
        /* 设置GPIOB0为输出引脚 */
        pReg = (unsigned int *)(0x40010C00 + 0x00);
        *pReg |= (1<<0);
        
        
        pReg = (unsigned int *)(0x40010C00 + 0x0C);
        while(1)
        {
            /* 设置GPIOB0输出高电平 */
            *pReg |= (1<<0);
            delay(100000);
            
            /* 设置GPIOB0输出低电平 */
            *pReg &= ~(1<<0);
            delay(100000);
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    再由启动文件:start.S调用main函数,参考keil自带的tartup_stm32f10x_hd.s

    设置栈,调用main函数:

                    PRESERVE8
                    THUMB
                  
                    AREA    RESET, DATA, READONLY
                    EXPORT  __Vectors    
                    
                    
    __Vectors       DCD     0               ; Top of Stack
                    DCD     Reset_Handler              ; Reset Handler
                        
                        
                    AREA    |.text|, CODE, READONLY
    
    ; Reset handler
    Reset_Handler   PROC
                    EXPORT  Reset_Handler             [WEAK]
                    IMPORT  main
                    
                    
                    LDR SP, =(0X20000000+0XC000)
                    BL      main
                    
                    ENDP
                    END
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    在这里插入图片描述

  • 相关阅读:
    Jetpack:012-Jetpack中的弹出菜单
    搭建自己的视频通话服务器Janus(WebRTC)
    程序设计与算法(三)C++面向对象程序设计笔记 第七周 输入输出和模板
    我们来浅谈代码语言的魅力
    bean的生命周期(最全最细讲解)
    Uboot spi-nor 设备信息定义及3地址模式和4地址模式的理解
    Docker-harbor私有仓库部署与管理
    Mybatis源码分析
    2023李宏毅机器学习HW05样例代码中文注释版
    数据对比与处理利器——Pandas 实战
  • 原文地址:https://blog.csdn.net/Caramel_biscuit/article/details/134246410