国民技术
直播中

知之为知之zhl

4年用户 99经验值
擅长:可编程逻辑 电源/新能源
私信 关注
[经验]

【国民技术N32项目移植】N32的bit-band操作

N32是Cortex-M4内核,看用户手册发现N32G457是有位带别名区的

手册中有这样两段话:
addr.png
bitband.png

对于N32的库中有关GPIO有GPIO_Module结构体,其中POD和PID为控制十六个管脚的输出与输入寄存器,使用位带别名区可以将单个管脚1bit的控制位扩展到32位,实现类似PA0 = 1;代码操作IO输出。

gpio.png

/**
 * [url=home.php?mod=space&uid=2666770]@Brief[/url] General Purpose I/O
 */

typedef struct
{
    __IO uint32_t PL_CFG;
    __IO uint32_t PH_CFG;
    __IO uint32_t PID;
    __IO uint32_t POD;
    __IO uint32_t PBSC;
    __IO uint32_t PBC;
    __IO uint32_t PLOCK_CFG;
    uint32_t RESERVED0;
    __IO uint32_t DS_CFG;
    __IO uint32_t SR_CFG;
} GPIO_Module;

实现手册内的公式,最终代码如下

/**
 * @author: Pomin
 * @date: 2022-10-29 20:12:56
 * @github: https://github.com/POMIN-163
 * @lastedit: 2022-12-22 16:42:50
 * @description: 别名区
 **/
#ifndef _ALIAS_REG_H
#define _ALIAS_REG_H

#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif

#include <stdio.h>

#include "n32g45x.h"

// 位带操作
// 公式:
//      最终地址 = 别名区基址 + ((A ‐ 外设基址)*8 + n)*4 = 别名区基址 + (A ‐ 外设基址)*32 + n*4
// 解释:
//      原地址相对外设基址偏移值膨胀 32 倍得到外设在别名区的基址
//      原 1 bit变为 32bit, + n*4 找到第n个管脚 (*4)是表示四个字节即 32bit

#define MCU_PERIPH_BASE    PERIPH_BASE     // 外设基址
#define MCU_PERIPH_BB_BASE PERIPH_BB_BASE  // 别名区基址

#define MEM_ADDR(addr)    (*((volatile unsigned long *)(addr)))            // 一个数字转为地址并取值
#define DIFF_ADDR(addr)   ((uint32_t)(addr) - (uint32_t)MCU_PERIPH_BASE)   // 地址相对外设基址偏移
#define BIT_BAND(addr)    ((MCU_PERIPH_BB_BASE + (DIFF_ADDR(addr) << 5)))  // 位带膨胀后的基址
#define BIT_REG(reg, bit) ((uint32_t *)BIT_BAND(&(reg)))[bit]              // 算出原来的1bit 膨胀后的地址
// #define BIT_REG(reg, bit) MEM_ADDR((BIT_BAND(&(reg)) + (((uint32_t)(bit)) << 2)))

#define PA ((uint32_t *)BIT_BAND(&(GPIOA->POD)))  // 此写法可以写成 PA[10] = 1;
#define PB ((uint32_t *)BIT_BAND(&(GPIOB->POD)))
#define PC ((uint32_t *)BIT_BAND(&(GPIOC->POD)))
#define PD ((uint32_t *)BIT_BAND(&(GPIOD->POD)))
#define PE ((uint32_t *)BIT_BAND(&(GPIOE->POD)))
#define PF ((uint32_t *)BIT_BAND(&(GPIOF->POD)))
#define PG ((uint32_t *)BIT_BAND(&(GPIOG->POD)))

#define PAout(n) BIT_REG(GPIOA->POD, n)  // 此写法可以写成 PAout(1) = 1;
#define PBout(n) BIT_REG(GPIOB->POD, n)
#define PCout(n) BIT_REG(GPIOC->POD, n)
#define PDout(n) BIT_REG(GPIOD->POD, n)
#define PEout(n) BIT_REG(GPIOE->POD, n)
#define PFout(n) BIT_REG(GPIOF->POD, n)
#define PGout(n) BIT_REG(GPIOG->POD, n)

#define PAin(n) BIT_REG(GPIOA->PID, n)
#define PBin(n) BIT_REG(GPIOB->PID, n)
#define PCin(n) BIT_REG(GPIOC->PID, n)
#define PDin(n) BIT_REG(GPIOD->PID, n)
#define PEin(n) BIT_REG(GPIOE->PID, n)
#define PFin(n) BIT_REG(GPIOF->PID, n)
#define PGin(n) BIT_REG(GPIOG->PID, n)

#ifdef __cplusplus
}
#endif
#endif  // _ALIAS_REG_H

用位带别名区控制闪灯

while (1) {

        delay_ms(500);

        PA[8] ^= 1;

        PB[4] ^= 1;

        PB[5] ^= 1;

    }

功能正常

更多回帖

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