欧启标O老师STM32课程笔记(一)——点亮LED灯

        笔者初学单片机,直接学习STM32,用的是正点原子的F1精英系列开发板,本来照着B站上正点原子的官方教程学习,但是学习一段时间后,发现该教程某些地方讲的不尽如人意,一番比较之后,笔者选择了欧启标老师的课程(【1.1STM32入门_实操_点亮一颗LED灯】1.1STM32入门_实操_点亮一颗LED灯_哔哩哔哩_bilibili  ,正点原子官方也发布了同一套视频 【【新手入门】STM32从0到1,从浅至深知识讲解-原子哥强烈推荐!】【新手入门】STM32从0到1,从浅至深知识讲解-原子哥强烈推荐!_哔哩哔哩_bilibili)。但是,课程中使用的单片机为stm32 F4系列,F4与F1系列有较多不同之处。所以,本文在记录欧启标老师课上所讲知识之外,也附上笔者根据欧启标老师课上的F4代码修改得到的F1的对应代码。

        本笔记是按照欧启标老师课程整理而来,若与课程有不同之处,则以课程为准。笔者初学单片机,难免有一些错误,希望各位网友批评指正。

1.1 点亮LED灯

        keil的安装、破解、美化、新建工程等教程网上已有很多,不再赘述。本文直接从 1.1 点亮LED灯开始。

1.1.1 电路原理

        此电路原理非常简单,LED0、LED1阳极均与3.3V电压相连,阴极分别与PB5、PE5相连。若想点亮二极管,使对应管脚置低电平即可,但在设置引脚输出为低电平时,需要配置对应IO口的时钟,并设置输出模式。

欧启标O老师STM32课程笔记(一)——点亮LED灯_第1张图片

欧启标O老师STM32课程笔记(一)——点亮LED灯_第2张图片

由以上分析,点亮LED0实现步骤为:

        1 使能PB时钟

        2 设置引脚为输出模式

        3 设置低电平

下面,结合数据手册分析如何实现以上三个步骤。

1.1.2 使能PB时钟

        使能IO端口时钟对应的寄存器为:RCC_APB2ENR

        该寄存器各位对应的功能为(部分):

欧启标O老师STM32课程笔记(一)——点亮LED灯_第3张图片

        可以看到,若要使能IOPB,使RCC_APB2ENR寄存器bit3置1即可。也即 RCC_APB2ENR|= 1<<3;

        (初学者应适应这种操作bit的方式,1<<3即为 0000 0000 0000 0000 0000 0000 0000 1000,RCC_APB2ENR|(1<<3)的效果是将bit3置1,同时不改变其他bit的值。)

1.1.3 设置引脚为输出模式:

        stm32 F1有7组GPIO,每组GPIO有16个gpio口(0-15),配置每个gpio口需要4位配置寄存器,所以需要64位,即两个32位,0-7为端口配置低寄存器GPIOx_CRL ,8-15为端口配置高寄存器GPIOx_CRH。由于LED0对应的是PB5,所以应配置GPIOx_CRL 。

        由下图,PB5对应的bit为23:20,将位23:33置成00,位21:20置成01、10、11均可。也即GPIOB_CRL|=1<<20;(置为01)

        注意:在配置寄存器时,有可能寄存器中原本有值,会影响赋值结果,因此,赋值前应将对应位清零,也即GPIOB_CRL&= ~(15<<20) (该写法与上面类似,~(15<<20)=1111 0000 1111 1111 1111 1111 1111,与运算后,只将第23-20位置0,并不改变其他位的值)

欧启标O老师STM32课程笔记(一)——点亮LED灯_第4张图片

1.1.4 设置输出为低电平:

        端口输出对应的寄存器为:GPIOx_ODR,该寄存器的16位与IO口的16位一一对应,将寄存器的某一位设置成1,则对应端口输出高电平,反之输出低电平。

欧启标O老师STM32课程笔记(一)——点亮LED灯_第5张图片

        设置PB5输出低电平,应使GPIOB_ODR的bit5置成0,也即 GPIOB_ODR &= ~(1<<5)

(该写法与上面类似,~(1<<5)=1111 1111 1111 1111 1111 1110 1111,与运算后,只将第五位置成0,并不改变其他位的值)

        经过以上分析,可以得到以下代码:

RCC_APB2ENR|= 1<<3;
GPIOB_CRL&= ~(15<<20);
GPIOB_CRL|=1<<20;
GPIOB_ODR &= ~(1<<5);

        但是,RCC_APB2ENR、GPIOB_CRL、GPIOB_ODR均代表的是单片机内寄存器的地址,如果我们不声明的话,编译器是识别不到这些地址的,所以,我们应当加以声明。可以从参考手册获取寄存器地址。

        寄存器的地址是由基地址和偏移地址组成,查找手册,可以看到RCC寄存器的基地址为:0x4002 1000,而APB2ENR相对于RCC的偏移地址为0x18,所以,RCC_APB2ENR的地址为:

        0x4002 1000+0x18=0x4002 1018

欧启标O老师STM32课程笔记(一)——点亮LED灯_第6张图片

欧启标O老师STM32课程笔记(一)——点亮LED灯_第7张图片

        与上面计算过程一致,GPIOB_CRL的地址为:

                0x4001 0c00+0x00=0x4001 0c00

        GPIOB_ODR的地址为:

                0x4001 0c00+0x0C=0x4001 0c0c

欧启标O老师STM32课程笔记(一)——点亮LED灯_第8张图片

欧启标O老师STM32课程笔记(一)——点亮LED灯_第9张图片

欧启标O老师STM32课程笔记(一)——点亮LED灯_第10张图片

所以,STM32F1上完整代码为:

#define RCC_APB2ENR  (*(volatile unsigned int*)(0x40021018))
#define GPIOB_CRL  (*(volatile unsigned int*)(0x40010c00))
#define GPIOB_ODR  (*(volatile unsigned int*)(0x40010c0c))
//0x40021018是一个数字---->(*)0x40021018 加星号变成地址---->(*(*)0x40021018) 地址指向的存储单元
//---->(*(unsigned int*) (0x40021000+0x18)) 地址指向的存储单元中存储的数据类型是unsigned int---->
//(*(volatile unsigned int*) (0x40021000+0x18)) 直接访问地址,不要去缓存访问
//
int main()
{
    //使能GPIOB时钟
    RCC_APB2ENR |= (1<<3);
    //设置PB5的功能
    GPIOB_CRL&= ~(15<<20);
    GPIOB_CRL|=1<<20;
    //设置PB5输出高电平,LED灭
    GPIOB_ODR |= (1<<5);;
    while(1)
    {
        GPIOB_ODR &=~(1<<5);//LED亮
    }
    // return 0;
}

欧启标老师STM32F4上完整代码为:

/* GPIOF 口相关寄存器的定义 */
#define GPIOF_MODER (*(volatile unsigned *)0x40021400) //端口 x 输入输出模式配置寄存器
#define GPIOF_ODR (*(volatile unsigned *)0x40021414) //端口输出数据寄存器
/* 时钟系统相关寄存器的定义 */
#define RCC_AHB1ENR (*(volatile unsigned *)0x40023830) //外设时钟使能寄存器
/* 主函数定义 */
int main(void)
{
	RCC_AHB1ENR |= (1<<5); //使能 PORTF 时钟
	GPIOF_MODER &= ~(3<<(9*2)); //将配置 PF9 引脚相关位 bit18,bit19 清 0
	GPIOF_MODER |= (1<<(9*2)); //将模式寄存器的 bit19、bit18 设置为 01
	GPIOF_ODR |= (1<<9); //LED0 灭
	while(1)
	{
		GPIOF_ODR &= ~(1<<9); //LED0 亮
	}
}

附:GPIO配置对应的寄存器:

        两个32位配置寄存器(GPIOx_CRL ,GPIOx_CRH)

        两个32位数据寄存器 (GPIOx_IDR和GPIOx_ODR),

        一个32位置位/ 复位寄存器(GPIOx_BSRR),

        一个16位复位寄存器(GPIOx_BRR),

        一个32位锁定寄存器(GPIOx_LCKR)。

        (1)配置寄存器:stm32有7组GPIO,每组GPIO有16个gpio口(0-15),配置每个gpio口需要4位配置寄存器,所以需要64位,即两个32位,0-7为端口配置低寄存器GPIOx_CRL ,8-15为端口配置高寄存器GPIOx_CRH。

        (2)数据寄存器

                端口输入数据寄存器GPIOx_IDR: 每个IO口一位,一组16位。

                端口输出数据寄存器GPIOx_ODR:每个IO口一位,一组16位。

        (3)端口位设置/清除寄存器GPIOx_BSRR:

                高位BR:每个io对应一位,若设置为1,则设置对应的DDR寄存器位为0,若设置为0,则对对应的DDR位不产生影响。

                低位BS:每个io对应一位,若设置为1,则设置对应的DDR寄存器位为1,若设置为0,则对对应的DDR位不产生影响。

                BS优先级大于BR。

你可能感兴趣的:(STM32,stm32,单片机,arm)