STM32F4寄存器编写跑马灯例程

发布者:三青最新更新时间:2020-09-04 来源: eefocus关键字:STM32F4  寄存器  跑马灯 手机看文章 扫描二维码
随时随地手机看文章

最近由于在学习STM32看到别人用寄存器编程控制跑马灯,于是自己也想试一试。可是试了好久终究弄不出来。回头看了下库函数的调用关系才搞明白。首先通过查看GPIOA的设置函数发现设置如下:


void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)

{

  uint32_t pinpos = 0x00, pos = 0x00 , currentpin = 0x00;


  /* Check the parameters */

  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));

  assert_param(IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin));

  assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode));

  assert_param(IS_GPIO_PUPD(GPIO_InitStruct->GPIO_PuPd));


  /* ------------------------- Configure the port pins ---------------- */

  /*-- GPIO Mode Configuration --*/

  for (pinpos = 0x00; pinpos < 0x10; pinpos++)

  {

    pos = ((uint32_t)0x01) << pinpos;

    /* Get the port pins position */

    currentpin = (GPIO_InitStruct->GPIO_Pin) & pos;


    if (currentpin == pos)

    {

      GPIOx->MODER  &= ~(GPIO_MODER_MODER0 << (pinpos * 2));

      GPIOx->MODER |= (((uint32_t)GPIO_InitStruct->GPIO_Mode) << (pinpos * 2));


      if ((GPIO_InitStruct->GPIO_Mode == GPIO_Mode_OUT) || (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_AF))

      {

        /* Check Speed mode parameters */

        assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed));


        /* Speed mode configuration */

        GPIOx->OSPEEDR &= ~(GPIO_OSPEEDER_OSPEEDR0 << (pinpos * 2));

        GPIOx->OSPEEDR |= ((uint32_t)(GPIO_InitStruct->GPIO_Speed) << (pinpos * 2));


        /* Check Output mode parameters */

        assert_param(IS_GPIO_OTYPE(GPIO_InitStruct->GPIO_OType));


        /* Output mode configuration*/

        GPIOx->OTYPER  &= ~((GPIO_OTYPER_OT_0) << ((uint16_t)pinpos)) ;

        GPIOx->OTYPER |= (uint16_t)(((uint16_t)GPIO_InitStruct->GPIO_OType) << ((uint16_t)pinpos));

      }


      /* Pull-up Pull down resistor configuration*/

      GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPDR0 << ((uint16_t)pinpos * 2));

      GPIOx->PUPDR |= (((uint32_t)GPIO_InitStruct->GPIO_PuPd) << (pinpos * 2));

    }

  }

}

GPIO_TypeDef端口设置结构体如下:

typedef struct

{

  __IO uint32_t MODER;    /*!< GPIO port mode register,               Address offset: 0x00      */

  __IO uint32_t OTYPER;   /*!< GPIO port output type register,        Address offset: 0x04      */

  __IO uint32_t OSPEEDR;  /*!< GPIO port output speed register,       Address offset: 0x08      */

  __IO uint32_t PUPDR;    /*!< GPIO port pull-up/pull-down register,  Address offset: 0x0C      */

  __IO uint32_t IDR;      /*!< GPIO port input data register,         Address offset: 0x10      */

  __IO uint32_t ODR;      /*!< GPIO port output data register,        Address offset: 0x14      */

  __IO uint16_t BSRRL;    /*!< GPIO port bit set/reset low register,  Address offset: 0x18      */

  __IO uint16_t BSRRH;    /*!< GPIO port bit set/reset high register, Address offset: 0x1A      */

  __IO uint32_t LCKR;     /*!< GPIO port configuration lock register, Address offset: 0x1C      */

  __IO uint32_t AFR[2];   /*!< GPIO alternate function registers,     Address offset: 0x20-0x24 */

} GPIO_TypeDef;

改机构体根据结构体成员函数的大小自己形成了针对首地址的偏移量。从而与需要操作的寄存器地址偏移一一对应。通过查看设置函数可以看出,初始设置需要进行几步必要的设置,经过实验发现只需要设置


GPIOx->MODER和时钟就可以。同时需要对GPIO 端口置位/复位寄存器进行操作。由该寄存器可以知,低16位置位1,高16位复位0。由此得出寄存器操作代码如下:

//#define GPIPA  *(volatile unsigned long *)0x40020000;

#define  GPIOA_MODER  *(volatile unsigned long *)0x40020000

#define GPIOA_OSPEEDR *(volatile unsigned long *)0x40020008

#define GPIOA_OTYPER *(volatile unsigned long *)0x40020004

#define GPIOA_PUPDR *(volatile unsigned long *)0x4002000C

#define RCC_AHB1ENR *(volatile unsigned long *)0x40023830

#define    GPIOA_BSRR *(volatile unsigned long *)0x40020018

//typedef struct


//{

 // __IO uint32_t MODER;    /*!< GPIO port mode register,               Address offset: 0x00      */

 // __IO uint32_t OTYPER;   /*!< GPIO port output type register,        Address offset: 0x04      */

 // __IO uint32_t OSPEEDR;  /*!< GPIO port output speed register,       Address offset: 0x08      */

//  __IO uint32_t PUPDR;    /*!< GPIO port pull-up/pull-down register,  Address offset: 0x0C      */

 // __IO uint32_t IDR;      /*!< GPIO port input data register,         Address offset: 0x10      */

//  __IO uint32_t ODR;      /*!< GPIO port output data register,        Address offset: 0x14      */

//  __IO uint16_t BSRRL;    /*!< GPIO port bit set/reset low register,  Address offset: 0x18      */

//  __IO uint16_t BSRRH;    /*!< GPIO port bit set/reset high register, Address offset: 0x1A      */

//  __IO uint32_t LCKR;     /*!< GPIO port configuration lock register, Address offset: 0x1C      */

//  __IO uint32_t AFR[2];   /*!< GPIO alternate function registers,     Address offset: 0x20-0x24 */

//} GPIO_TypeDef;

void delay_ms(int time)

{

  int i=8000*time;

  while(i--);

}


int main(void)

{

//    delay_init(168);

    int i = 0, j = 0, k = 0;


    RCC_AHB1ENR |= 0x00000001;

    GPIOA_MODER &= ~((3<<(6*2))|(3<<(7*2)));

    GPIOA_MODER |= (1<< (6*2))|(1<<(7*2));

    GPIOA_BSRR &= 0x0; //clear

    /* Speed mode configuration */

//    GPIOA_OSPEEDR &= ~((3<<(6*2))|(3<<(7*2)));

//    GPIOA_OSPEEDR |= (3 << (6 * 2))|(3 << (7 * 2));

    

    /* Output mode configuration*/

//    GPIOA_OTYPER  &= ~((3<<6)|(3<<7)) ;

//    GPIOA_OTYPER |= (0 << 6)|(0 << 7);


      /* Pull-up Pull down resistor configuration*/

//     GPIOA_PUPDR &= ~((3<<(6*2))|(3<<(7*2)));

//     GPIOA_PUPDR |= (1<< (6*2))|(1<<(7*2));

//    GPIOA_BSRRL = 0x0040|0x0080;

    

    while(1)

    {

            

            GPIOA_BSRR = (0x0040|0x0080)<<16; //reset

            delay_ms(1000);

            GPIOA_BSRR = 0x0040|0x0080; //set

            delay_ms(1000);

            

    }

}




void SystemInit()

{

    ;

以上代码便可以实现流水灯例子。


关键字:STM32F4  寄存器  跑马灯 引用地址:STM32F4寄存器编写跑马灯例程

上一篇:STM32F4外设驱动系列之GPIO
下一篇:STM32学习笔记之GPIO(二)

推荐阅读最新更新时间:2024-11-09 18:26

stm8l低功耗系列
最近干刚做了一个stm8的项目用的是L低功耗系列,其中遇到一个问题。外设寄存器的值怎么都写入不进去。用IAR仿真产看寄存器的值,不论写进去多少,都是初始值。后来把所有寄存器都写了一遍,发现有的能写进去,有的写不进去。比如GPIO的寄存器就能写进去。百思不得姐,偶然查看clock的库函数发现个函数是设置外设时钟的。这个系列,亦或者整个低功耗系列的每个外设是不是都需要在时钟寄存器中单独设置时钟。(以前所使用的芯片都是在外设寄存器中使能或者是禁使能)
[单片机]
STM32通定时器时间设置步骤和计算公式方法寄存器
一、STM32通用定时器原理 STM32 系列的CPU,有多达8个定时器,其中TIM1和TIM8是能够产生三对PWM互补输出的高级定时器,常用于三相电机的驱动,它们的时钟由APB2的输出产生。其它6个为普通定时器,时钟由APB1的输出产生。 下图是STM32参考手册上时钟分配图中,有关定时器时钟部分的截图: 从图中可以看出,定时器的时钟不是直接来自APB1或APB2,而是来自于输入为APB1或APB2的一个倍频器,图中的蓝色部分。 下面以通用定时器2的时钟说明这个倍频器的作用:当APB1的预分频系数为1时,这个倍频器不起作用,定时器的时钟频率等于APB1的频率;当APB1的预分频系数为其它数值(
[单片机]
STM32通定时器时间设置步骤和计算公式方法<font color='red'>寄存器</font>值
STM32F407ZGT6芯片时钟系统模块介绍
STM32F4时钟系统的知识在《STM32F4中文参考手册》第六章复位和时钟控制章节有非常详细的讲解,网上关于时钟系统的讲解也有很多,讲不出啥特色,时钟模块是芯片非常重要的组成部分,我们必然要提到时钟系统的知识。这些知识也不是什么原创,纯粹根据官方提供的中文参考手册和自己的应用心得来总结的,如有不合理之处望大家谅解。 STM32F4时钟树概述 众所周知,时钟系统是CPU的脉搏,就像人的心跳一样。所以时钟系统的重要性就不言而喻了。STM32F4的时钟系统比较复杂,不像简单的51单片机一个系统时钟就可以解决一切。于是有人要问,采用一个系统时钟不是很简单吗?为什么STM32要有多个时钟源呢?因为首先STM32本身非常复杂,外设非常的
[单片机]
<font color='red'>STM32F4</font>07ZGT6芯片时钟系统模块介绍
AT89S52单片机介绍_AT89S52单片机主要性能及寄存器
AT89S52是一种低功耗、高性能CMOS8位微控制器,具有8K系统可编程Flash存储器。使用Atmel公司高密度非易失性存储器技术制造,与工业80C51产品指令和引脚完全兼容。片上Flash允许程序存储器在系统可编程,亦适于常规编程器。在单芯片上,拥有灵巧的8位CPU和在系统可编程Flash,使得AT89S52在众多嵌入式控制应用系统中得到广泛应用。 AT89S52主要性能 1、与MCS-51单片机产品兼容; 2、8K字节在系统可编程Flash存储器; 3、1000次擦写周期; 4、全静态操作:0Hz-33MHz; 5、三级加密程序存储器; 6、32个可编程I/O口线; 7、三个16位定时器/计数器; 8、6个中断源; 9
[单片机]
AT89S52单片机介绍_AT89S52单片机主要性能及<font color='red'>寄存器</font>
STM32F429HAL库UART学习笔记
UART串口通讯作为最基本通讯协议我就不多赘述。我主要用HAL库实现串口通讯,看一下配置Uart的结构一变量 这里使用了结构体嵌套 typedef struct { USART_TypeDef *Instance; 串口类型和串口内部控制寄存器结构体 UART_InitTypeDef Init; 定义串口输出数据类型停止位奇偶校验位的结构体 uint8_t *pTxBuffPtr; 要发送的数据的缓冲数组指针 uint16_t TxXferSize; 要发送数组大小 uint16_t TxX
[单片机]
STM32F429 CAN2通信
CAN1和CAN2共用28个滤波器,因CAN2不能读取SRAM,故在单独使用CAN2时,需要先打开CAN1的时钟,然后通过CAN1来设置滤波器,完了再初始化CAN2即可实现数据收发。 CAN1的滤波器序号为0-13,CAN2的滤波器序号为14-27。 单独使用can2时,can1的时候也需要打开。 还有过滤器的设置 CAN2_FilerConf.FilterIdHigh=0X0000; //32位ID CAN2_FilerConf.FilterIdLow=0X0000; CAN2_FilerConf.FilterMaskIdHigh=0X0000; //32位MASK CAN2_FilerConf.Fi
[单片机]
STM32F429之GPIO使用
STM32 IO模式 (1)浮空输入_IN_FLOATING ——浮空输入,可以做KEY识别,RX1 (2)带上拉输入_IPU——IO内部上拉电阻输入 (3)带下拉输入_IPD—— IO内部下拉电阻输入 (4) 模拟输入_AIN ——应用ADC模拟输入,或者低功耗下省电 (5)开漏输出_OUT_OD ——IO输出0接GND,IO输出1,悬空,需要外接上拉电阻,才能实现输出高电平。当输出为1时,IO口的状态由上拉电阻拉高电平,但由于是开漏输出模式,这样IO口也就可以由外部电路改变为低电平或不变 。可以读IO输入电平变化,实现C51的IO双向功能 (6)推挽输出_OUT_PP ——IO输出0-接GND, IO输出1 -接VCC,读输
[单片机]
stm32f4 DMA任意长度buffer无停顿传输
最近闲来无事,玩起了之前自己打的一块f407开发板,做一些VGA分辨率下的模式识别. 我的板上外扩有2兆的SRAM,之前一直用QVGA作图像源,算法能跑到15帧,还算不错. 我的方式是dcmi数据DMA到外扩SRAM,SRAM中处理,结果拷贝到LCD.改到VGA分辨率后问题来了. 图像错乱,但局部图像可以看出摄像头正确的输出 ,整个画面像一张位置错乱的拼图。 据此排除了摄像头输出格式的问题,那么很有可能是显示遮盖造成的。到底是什么原因呢? 几经排查,发现当我修改DMA的buffer size 时,画面会呈现截然不同的组合,难道是DMA的问题? 查阅资料才发现,自己之前对于buffer size的认识是错误的。在地址自增模式下,b
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved