GD32 寄存器操作按键点灯(裸机开发)

裸机开发流程

1.准备好当前开发板的原理图,还有芯片手册。
开发板:GD32C103RB
开发板主图
在这里插入图片描述
芯片手册
在这里插入图片描述
2.看原理图找到你要操作的硬件,对应的管脚

3.看芯片手册,怎么配置这个硬件,怎么操作这个硬件

4.编写C代码(或者汇编代码)

开发思路

1.裸机点亮D2 就是led1

打开时钟
GPIO是在APB2总线上,找到该总线的时钟,在第五章
只关注APB2时钟使能    偏移:0x18
RCU基地址:0x4002 1000
0x4002 10184位置一
4 PCEN GPIO端口C时钟使能
由软件置位或复位
0:关闭GPIO端口C时钟
1:开启GPIO端口C时钟
#define RCU_CON *(unsigned int *)(0x40021018)
//打开GPIO时钟
RCU_CON |= (0x1<<4);

GPIOC基地址:0x4001 1000    这个表示C口的基地址

端口控制寄存器 0 (GPIOx_CTL0, x=A..E)
	地址偏移:0x00
	
端口控制寄存器 1 (GPIOx_CTL1, x=A..E)   一个找10号引脚
	地址偏移:0x04
配置:
	11:10 CTL10[1:0] Port 10配置位   也就是pin10
        该位由软件置位和清除。
        输入模式 ( MD[1:0] =00)
        00: 模拟输入
        01: 浮空输入
        10: 上拉输入 /下拉输入
        11: 保留
        输出模式 ( MD[1:0] >00)
        00: GPIO 推挽输出	GPIO output with push-pull  
        01: GPIO 开漏输出	
        10: AFIO 推挽输出   
        11: AFIO 开漏输出
        
        0x4001 1004[11:10] = 0x00;
        
	9:8 MD10[1:0] Port10模式位
		该位由软件置位和清除。
        00: 输入模式 (复位状态)
        01: 输出模式,最大速度10MHz 
        10: 输出模式,最大速度2 MHz
        11: 输出模式,最大速度50MHz
        
        0x4001 1004[9:8] = 0x1
#define GPIOC_CON *(unsigned int *)(0x40011004)
//配置输入输出模式
GPIOC_CON &= ~(0xf<<8);	//清0	[8:11]
GPIOC_CON |= (0x1<<8);	//清0后把最后一位置1

基本上初始化完成。。。。

端口输出控制寄存器 (GPIOx_OCTL, x=A..E)
地址偏移:0x0C
复位值:0x0000 0000
0x4001100c 这个寄存器第10位置1 表示关灯 置0表示开灯
#define GPIOC_DATA *(unsigned int *)(0x4001100c)
GPIOC_DATA |= (0x1 << 10);	//关灯
GPIOC_DATA &= ~(0x1 << 10);	//开灯

2.裸机按钮key1

时钟:
3 PBEN GPIO端口B时钟使能
由软件置位或复位
0:关闭GPIO端口B时钟
1:开启GPIO端口B时钟
//第3位置1 打开B端口时钟
#define RCU_CON *(unsigned int *)(0x40021018)
RCU_CON |= (0x1<<3);

KEY1  -> PB12

GPIOB基地址:0x4001 0C00
端口控制寄存器 1 (GPIOx_CTL1, x=A..E)
	地址偏移:0x04
0x40010C04	悬浮输入 没有速度
[16:19] = 0x0100	
#define GPIOB_KEY1_CON *(unsigned int *)(0x40010C04)
//配置浮空输入
GPIOB_KEY1_CON &= ~(0xf<<16);	//清0	[8:11]
GPIOB_KEY1_CON |= (0x4<<16);	//清0后把最后一位置1

端口输入状态寄存器 (GPIOx_ISTAT, x=A..E)
地址偏移:0x08
0x40010C08
#define KEY1_STATUS *(unsigned int *)(0x40010C08)
//按键检测
if(0 == (KEY1_STATUS & (1<<12))){
	GPIOC_DATA &= ~(0x1 << 10);	//开灯
}

3.解决LED0

因为LED最开始不是GPIO的,打开备用功能才能使用GPIO输出

1.打开备用功能时钟 在main开头处
RCU基地址:0x4002 1000
APB2 使能寄存器 (RCU_APB2EN)  地址偏移: 0x18
	0 AFEN 复用功能IO时钟使能
	由软件置位或复位
    0: 关闭复用功能IO时钟
    1: 开启复用功能IO时钟
0x40021018 [0]1
#define RCU_CON *(unsigned int *)(0x40021018)
RCU_CON |= (0x1<<0);

2.关闭JTAD 打开SWJ
/*!< JTAG-DP disabled and SW-DP enabled */
#define GPIO_SWJ_SWDPENABLE_REMAP   ((uint32_t)0x00300000U | (PCF0_SWJ_CFG(2) >> 16)) SWJ _CFG[2:0] = 010   JTAG-DP 关闭 SW-DP 开启  
#define PCF0_SWJ_CFG(regval)      (BITS(24,26) & ((uint32_t)(regval) << 24))                        /*!< serial wire JTAG configuration */

AFIO基地址:0x4001 0000

AFIO 端口配置寄存器 0 (AFIO_ PCF0)  地址偏移:0x04
    0 SPI0_REMAP SPI0 重映射
    该位由软件置位和清除。
    0: 没有重映射 (SPI0_NSS/PA4, SPI0_SCK /PA5, SPI0_MISO /PA6, 
    SPI0_MOSI /PA7, SPI0_IO2 /PA2, SPI0_IO3 /PA3)
    1: 重映射 (SPI0_NSS/PA15, SPI0_SCK /PB3, SPI0_MISO /PB4,
    SPI0_MOSI /PB5, SPI0_IO2 /PB6, SPI0_IO3 /PB7)

    26:24 SWJ_CFG[2:0] 串行线JTAG配置
    这些位只写(读这些位,将返回未定义值)。用于配置SWJ和跟踪复用功能的I/O
    口。SWJ(串行线JTAG)支持JTAG或SWD访问Cortex调试端口。系统复位后的默
    认状态是启用SWJ但没有跟踪功能,这种状态下,可以通过在JTMS/JTCK引脚上的
    发送特定的信号使能JTAG或SW(串行线)模式。
    000: 完全SWJ(JTAG-DP +SW-DP):复位状态
    001: 完全SWJ(JTAG-DP +SW-DP):没有NJTRST 
    010: JTAG-DP禁用和SW-DP使能
    100: JTAG-DP禁用和SW-DP禁用
    其他组合: 无作用
    注意:每次只能设置三个比特中的一个。
    
0x40010804  [0] = 1   [24:26] = 010 

#define APIO_CON *(unsigned int *)0x40010804
//打开AFIO端口重映射
APIO_CON |= (0x1<<0);
//24-26位清零后再变成010
APIO_CON &= ~(0x1<<24);
APIO_CON |= (0x010<<24)


SPI0_NSS  SPI0_REMAP =1  PA15

GPIOA基地址:0x4001 0800
端口控制寄存器 1 (GPIOx_CTL1, x=A..E) 地址偏移:0x04
31:30 CTL15[1:0] Port 15配置位
    该位由软件置位和清除。
    参考CTL0[1:0]的描述
29:28 MD15[1:0] Port 15模式位
    该位由软件置位和清除。
    参考MD0 [1:0]的描述
[28:31] = 0001

#define GPIOA_CON *(unsigned int *)(0x40010804)
GPIOA_CON &= ~(0xf<<28);
GPIOA_CON |= (0x1<<28);

端口输出控制寄存器 (GPIOx_OCTL, x=A..E) 地址偏移:0x0C
[15] = 1
#define GPIOA_DATA *(unsigned int *)(0x4001080C)
GPIOA_DATA |= (0x1<<15);

寄存器操作按键点灯(裸机开发)代码

/********虽然导入了库函数,但一个不能用,这是裸机开发*****/
#include "gd32c10x.h"
#include "systick.h"
#include <stdio.h>
#include "main.h"
#include "gd32c10x_eval.h"

void led_spark(void)
{
    static __IO uint32_t timingdelaylocal = 0U;

    if(timingdelaylocal){

        if(timingdelaylocal < 500U){
            //gd_eval_led_on(LED2);
        }else{
            //gd_eval_led_off(LED2);
        }

        timingdelaylocal--;
    }else{
        timingdelaylocal = 1000U;
    }
}

//led and KEY  Register
#define RCU_CON *(unsigned int *)(0x40021018)
#define GPIOC_CON *(unsigned int *)(0x40011004)
#define GPIOC_DATA *(unsigned int *)(0x4001100c)
	
#define RCU_CON *(unsigned int *)(0x40021018)
#define GPIOB_KEY1_CON *(unsigned int *)(0x40010C04)
#define KEY1_STATUS *(unsigned int *)(0x40010C08)

//GPIOA port (config,data)
#define GPIOA_CON *(unsigned int *)(0x40010804)
#define GPIOA_DATA *(unsigned int *)(0x4001080C)

//AFIO 
#define AFIO_CON *(unsigned int *)(0x40010004)

//led on/off flag
int flag1 = 1;
int flag2 = 1;
int flag3 = 1;
int flag4 = 1;

int main(void)
{
		//打开AFIO时钟
		RCU_CON |= (0x1<<0);
		
		//AFIO重映射 关闭JTAG  打开SWD
		AFIO_CON |= (0x1<<0);
		AFIO_CON &= ~(0x7<<24);
		AFIO_CON |= (0x2<<24);
		
		//A
		RCU_CON |= (0x1<<2);
		
		/*GPIO output with push-pull 推挽输出    速度 speed:10MHZ  */
		//LED0 config  
		GPIOA_CON &= ~(0xf<<28);
		GPIOA_CON |= (0x1<<28);	
		
		//C port clock open
		RCU_CON |= (0x1<<4);
		
		//led1的配置 先清零再配置输出模式和速度
		GPIOC_CON = GPIOC_CON & (~(0xf<<8));
		GPIOC_CON |= (0x1<<8);
		
		//led2 config
		GPIOC_CON = GPIOC_CON & (~(0xf<<12));
		GPIOC_CON |= (0x1<<12);
		
		//led3 config
		GPIOC_CON = GPIOC_CON & (~(0xf<<16));
		GPIOC_CON |= (0x1<<16);
		
		
		//led off
		GPIOC_DATA |= (0x1 << 10);	
		GPIOC_DATA |= (0x1 << 11);
		GPIOC_DATA |= (0x1 << 12);
		GPIOA_DATA |= (0X1 << 15);
		
		
		//KEY B port clock open
		RCU_CON |= (0x1<<3);
		
		/*input:Floting悬浮输入    no speed 没有速度*/
		//KEY1 config
		GPIOB_KEY1_CON &= ~(0xf<<16);	
		GPIOB_KEY1_CON |= (0x4<<16);
		
		//KEY2 config
		GPIOB_KEY1_CON &= ~(0xf<<20);	
		GPIOB_KEY1_CON |= (0x4<<20);
		
		//KEY3 config
		GPIOB_KEY1_CON &= ~(0xf<<24);	
		GPIOB_KEY1_CON |= (0x4<<24);
		
		//KEY4 config
		GPIOB_KEY1_CON &= ~(0xf<<28);	
		GPIOB_KEY1_CON |= (0x4<<28);
		
    while (1){
			//KEY1 press 检测按键是否按下
			if(0 == (KEY1_STATUS & (1<<12))){				
				if(flag1){
					GPIOC_DATA &= ~(0x1 << 10);	//led on
					flag1 = 0;
				} else{
					GPIOC_DATA |= (0x1 << 10); //led off
					flag1 = 1;
				}
			}
			
			//KEY2 press
			if(0 == (KEY1_STATUS & (1<<13))){
					
				if(flag2){
					GPIOC_DATA &= ~(0x1 << 11);
					flag2 = 0;
				} else{
					GPIOC_DATA |= (0x1 << 11);
					flag2 = 1;
				}
			}
			
			//KEY3 press
			if(0 == (KEY1_STATUS & (1<<14))){
					if(flag3){
					GPIOC_DATA &= ~(0x1 << 12);
					flag3 = 0;
				} else{
					GPIOC_DATA |= (0x1 << 12);
					flag3 = 1;
				}
			}
			
			//KEY4 press
			if(0 == (KEY1_STATUS & (1<<15))){
					
					if(flag4){
						GPIOA_DATA &= ~(0X1 << 15);
						flag4 = 0;
					} else{
						GPIOA_DATA |= (0X1 << 15);
						flag4 = 1;
					}
			}
			
    }
}

总结

裸机开发最终要的就是熟悉如何得到寄存器地址#define RCU_CON *(unsigned int *)(0x40021018),还有移位操作,如何把寄存器置0,置1。想要设置多位必须先清0再置为你想要的参数。
操作一般都是打开某某功能的时钟,配置硬件相关的控制寄存器,然后对它的一些其他操作,GPIO就是输入、输出。

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是 GD32F3 的 GPIO 寄存器操作宏定义示例: ```c #define GPIO_BASE(port) (GPIOA_BASE + (port - GPIOA) * 0x0400U) // GPIO 基地址宏定义 #define GPIO_PIN(port, pin) (1U << (pin)) // GPIO 引脚宏定义 #define GPIO_MODER(port) (*(volatile uint32_t *)(GPIO_BASE(port) + 0x00U)) // GPIO 模式寄存器宏定义 #define GPIO_OTYPER(port) (*(volatile uint32_t *)(GPIO_BASE(port) + 0x04U)) // GPIO 输出类型寄存器宏定义 #define GPIO_OSPEEDR(port) (*(volatile uint32_t *)(GPIO_BASE(port) + 0x08U)) // GPIO 输出速度寄存器宏定义 #define GPIO_PUPDR(port) (*(volatile uint32_t *)(GPIO_BASE(port) + 0x0CU)) // GPIO 上下拉寄存器宏定义 #define GPIO_IDR(port) (*(volatile uint32_t *)(GPIO_BASE(port) + 0x10U)) // GPIO 输入数据寄存器宏定义 #define GPIO_ODR(port) (*(volatile uint32_t *)(GPIO_BASE(port) + 0x14U)) // GPIO 输出数据寄存器宏定义 #define GPIO_BSRR(port) (*(volatile uint32_t *)(GPIO_BASE(port) + 0x18U)) // GPIO 置位/复位寄存器宏定义 #define GPIO_LCKR(port) (*(volatile uint32_t *)(GPIO_BASE(port) + 0x1CU)) // GPIO 锁定寄存器宏定义 #define GPIO_AFRL(port) (*(volatile uint32_t *)(GPIO_BASE(port) + 0x20U)) // GPIO 复用功能低位寄存器宏定义 #define GPIO_AFRH(port) (*(volatile uint32_t *)(GPIO_BASE(port) + 0x24U)) // GPIO 复用功能高位寄存器宏定义 ``` 使用这些宏定义,可以方便地对 GD32F3 的 GPIO 寄存器进行操作,例如: ```c // 设置 GPIOA 的第 1 个引脚为输出模式,推挽输出,最大输出速度为 50MHz GPIO_MODER(GPIOA) |= (0x01U << (1U * 2U)); GPIO_OTYPER(GPIOA) &= ~(0x01U << 1U); GPIO_OSPEEDR(GPIOA) |= (0x03U << (1U * 2U)); // 设置 GPIOA 的第 2 个引脚为输入模式,上拉输入模式 GPIO_MODER(GPIOA) &= ~(0x03U << (2U * 2U)); GPIO_PUPDR(GPIOA) &= ~(0x03U << (2U * 2U)); GPIO_PUPDR(GPIOA) |= (0x01U << (2U * 2U)); // 读取 GPIOA 的第 2 个引脚的输入数据 uint32_t input_data = GPIO_IDR(GPIOA) & GPIO_PIN(GPIOA, 2U); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值