单片机学习小组
直播中

丁冬芹

7年用户 1271经验值
私信 关注

如何去实现基于stm32f103c8t6芯片的流水灯设计

STM32f103c8t6芯片是什么?

如何去实现基于stm32f103c8t6芯片的流水灯设计?

回帖(1)

张玉英

2022-2-23 15:26:58
一、原理介绍


1、 芯片介绍


STM32F系列属于中低端的32位ARM微控制器,该系列芯片是意法半导体(ST)公司出品,其内核是Cortex-M3



系列芯片按片内Flash的大小可分为三大类:小容量(16K和32K)、中容量(64K和128K)、大容量(256K、384K和512K)。

芯片集成定时器Timer,CAN,ADC,SPII2C,USB,UART等多种外设功能。

1.1、STMF103C8T6


首先介绍本文的主角了——stm32f103c8t6芯片,它是一款基于ARM Cortex-M 内核STM32系列的32位的微控制器程序存储器容量是64KB,需要电压2V~3.6V,工作温度为-40°C ~ 85°C。

32位指的是该芯片每次能同时处理的数据为4个字节共32位(bit),与以前我们学的51单片机一样,每次能够同时处理1个字节共8位数据,这对于我们在接下来寄存器的使用十分重要。

1.2、地址说明


这里给出 有关寄存器的地址,可以看见这里为寄存器的初始地址,而在后面我们会遇见一个偏移地址,这里给出寄存器的地址说明:



寄存器的具体地址=寄存器初始地址(基地址)+偏移地址


给出例子:例如GPIOA_CRH寄存器的基地址为0x4001 0800,后面的偏移地址为0x04

所以GPIOA_CRH寄存器的最终地址为0x4001 0804。同理,RCC_APB2ENR的地址为:

0x4002 1000 +0x18 =0x4002 1018。







通过系统图,我们可以看出ABP2寄存器与GPIOX输出端口相关联,所以接下来我们进行寄存器调用时便用RCC_ABP2外设时钟使能寄存器。

2、寄存器介绍


寄存器的功能是存储二进制代码,它是由具有存储功能的触发器组合起来构成的。一个触发器可以存储1位二进制代码,故存放n位二进制代码的寄存器,需用n个触发器来构成。

2.1、APB2 外设时钟使能寄存器(RCC_APB2ENR)


  根据实验需求,这里对后面将要用到的RCC寄存器做出说明;由图可见,为了实现流水灯,我们需要利用芯片的GPIOX引脚,RCC寄存器则具有控制GPIOX引脚的功能。







由上图可以清晰的看出,当对应的RCC位输出为1时,相应的GPIOX口开始工作。


  2.2、GPIO寄存器


接下来便是本文的重头戏,GPIO管脚的选择;GPIO寄存器下面总共又分为7种,分别是:



1、端口配置低寄存器(GPIOx_CRL) (x=A..E)

2、端口配置高寄存器(GPIOx_CRH) (x=A..E)

3、端口输入数据寄存器(GPIOx_IDR) (x=A..E)

4、端口输出数据寄存器(GPIOx_ODR) (x=A..E)

5、端口位设置/清除寄存器(GPIOx_BSRR) (x=A..E)

6、端口位清除寄存器(GPIOx_BRR) (x=A..E)

7、端口配置锁定寄存器(GPIOx_LCKR) (x=A..E)


首先,我们需要确定的是,在我们所看到的的芯片上PX0~PX15引脚在寄存器中分别对应的是什么位置,接下来给出简要说明:   

在芯片上我们可以看到总共有PX0~PX15号引脚,就拿PA脚来做说明,首先,上图所示,GPIOX_CRL总共有0~31共32位,而这32位又可以分为8组,每组分别是:CNF 和 MODE,所以我们用一组来对应其中的一个管脚,共8个脚;这里需要注意下,根据我们在单片机所学,地址又有高低之分,所以这里则代表了PA0~PA7八个低位管脚。



所以我们可以推出,GPIOX_CRH则代表了PA8~PA15八个高位管脚。


由图中可见,GPIOX_CLR只能给出输出的模式,而不是输出的值,所以接下来介绍,STM32芯片的输出寄存器。

2.3、端口输出数据寄存器(GPIOx_ODR)


我们可以清楚地知道,计算机的输出值只有2种:‘0’ 或者 ‘1’;现在来介绍如何实现值的输出:



  由图我们可以看到,GPIOX_ODR寄存器与之前的不同,这里只有0~15位可以用,上图我也标出,这15位分别代表着PX0~PX15共16个引脚,例如:PA1引脚我们就用到ODR1位置;PB5引脚我们就用ODR5位置,这样距离希望你们能够理解。。

好了,配置流水灯所需要的寄存器都已经进行说明,接下来就是如何利用寄存器来实现流水灯的运行。

二、C语言代码实现




代码实现思路:打开对应管脚的时钟——>配置输出,确定输出模式——>输出低电平——>实现流水灯


1、工程构建


在进行单片机以及ARM芯片的仿真以及代码嵌入,我们采用的软件一般为KEIl软件:

首先,新建工程:



选择工程放置的文件,并给出工程名称:



芯片选择:



相关环境的配置:



添加项目到工程中:



选择.c文件,并命名:



2、代码编写




根据上面我们所给出的实验思路,这里依据思路进行代码编写。


2.1、打开对应管脚




由于我采用的PA0、PB0、PC14三个管脚,所以这里对三个GPIO口进行激活,即使用位操作,将对应的为数变为1。


RCC_APB2ENR |=(1<<2);
RCC_APB2ENR |=(1<<3);
RCC_APB2ENR |=(1<<4);
2.2、 配置输出,确定输出模式




这里的&运算以及|运算,是对相应的PX管脚进行输出模式操作;由于CRL寄存器共有32位,所以这里采用8位的16进制来直接赋值(每一位16进制对应着4位2进制)。


GPIOA_CRL &=0xFFFFFFF0;
GPIOA_CRL |=0xFFFFFFF3;
      
GPIOB_CRL &=0xFFFFFFF0;
GPIOB_CRL |=0xFFFFFFF3;

GPIOC_CRH &=0xF0FFFFFF;
GPIOC_CRH |=0xF3FFFFFF;

2.3、输出低电平




我采用的是低电平点亮LED,高电平点灭LED


GPIOA_ODR =0x0<<0;
Delay_ms(10000000);
GPIOA_ODR =0x1<<0;
Delay_ms(10000000);

GPIOB_ODR =0;
Delay_ms(10000000);      
GPIOB_ODR =1;
Delay_ms(10000000);

GPIOC_ODR =0<<14;
Delay_ms(10000000);
GPIOC_ODR =1<<14;
Delay_ms(10000000);
2.4、延时操作




注意:这里采用延时函数是为了实现LED循环点亮点灭的操作


int  Delay_ms(volatile unsigned int time)
{   
        int i;
   while(time--)
   {
      i=20000;  
      while(i--) ;   
   }
         return 0;
}
2.5、完整代码


#define RCC_APB2ENR *(unsigned int*)0x40021018
#define GPIOA_CRL        *(unsigned int*)0x40010800
#define GPIOB_CRL *(unsigned int*)0x40010C00
#define GPIOC_CRH *(unsigned int*)0x40011004
#define GPIOA_ODR *(unsigned int*)0x4001080C
#define GPIOB_ODR *(unsigned int*)0x40010C0C
#define GPIOC_ODR *(unsigned int*)0x4001100C
      
int  Delay_ms(volatile unsigned int time)
{   
        int i;
   while(time--)
   {
      i=20000;  
      while(i--) ;   
   }
         return 0;
}

int main()
{
        RCC_APB2ENR |=(1<<2);
        RCC_APB2ENR |=(1<<3);
        RCC_APB2ENR |=(1<<4);
      
        while(1)
        {               
        GPIOA_CRL &=0xFFFFFFF0;
        GPIOA_CRL        |=0xFFFFFFF3;
        GPIOA_ODR =0x0<<0;
        Delay_ms(10000000);
        GPIOA_ODR =0x1<<0;
        Delay_ms(10000000);
      
        GPIOB_CRL &=0xFFFFFFF0;
        GPIOB_CRL |=0xFFFFFFF3;
        GPIOB_ODR =0;
        Delay_ms(10000000);
        GPIOB_ODR =1;
        Delay_ms(10000000);
      
        GPIOC_CRH &=0xF0FFFFFF;
        GPIOC_CRH |=0xF3FFFFFF;
  GPIOC_ODR =0<<14;
        Delay_ms(10000000);
        GPIOC_ODR =1<<14;
        Delay_ms(10000000);
}
}
三、仿真运行,并利用KEIL软件示波器进行输出口观察


首先,进行虚拟仿真环境配置:


文件编译,并开始运行:




打开keil软件示波器:





波形显示:



四、hex文件烧录


首先我们需要在keil下生成hex文件:



常用的烧录软件一般为:mcusip软件


关于该软件的使用方法我就不做过多说明: 这里我给出可以参考的链接,有需要的可以直接去查看,步骤写的很清楚,有很大的借鉴价值。

这里需要补充说明一下,在进行芯片烧录时,需要注意将芯片上的boot置1,在烧录完毕后,再讲其改为0。    十分重要!!!!

五、结果展示


六、总结


本次实验,主要是考验我们对于STM32芯片寄存器地址的了解,以及其各寄存器功能的了解。想要顺利的完成本次实验就需要去查阅大量的书籍资料,这里我推荐去STM32官网寻找,上面有着stm各系列的编程资料以及芯片手册。虽然,stm32有着更为简单的操作方式即库函数,但对于初学者来说,还是一步一步,脚踏实地的通过了解寄存器来完成才对于提高自己有着帮助。其次,KEIL自带的示波器还是挺好用的,这对于我们观察输出的结果很有帮助。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分