寄存器初识----stm32f103rbt6

(由于第一次在自带的浏览器写,结果在粘贴代码时网页卡死,没有保存。。。所以没了。。。这是第二次写,所以介绍简略了许多)
目的:通过对寄存器的操作,点亮LED;
参考文档:国信长天嵌入式竞赛平台原理图,stm32f103rbt6 ,
STM32中文参考手册_V10,Cortex-M3权威指南(中文)

通过对文档的翻阅,我们知道了LED1-8使用的是开发板的PC8-15;即GPIO的C端口的第8-15位;
其中,外设基地址是0x40000000;APB2的偏移地址是0x10000,GPIO接口都挂接在APB2总线上;
GPIOC的偏移地址是0x1000,保存着操作GPIO口的一些寄存器;
端口配置低寄存器GPIOC_CRL的偏移是0x00;端口配置高寄存器GPIOC_CRH的偏移是0x04,用来配置IO模式,俩个寄存器共64位,每4位可以配置一个IO位线的模式,可以配置0-15共16根位线;
GPIOC_ODR的偏移是0x0C;用来输出数据,通过实验发现,输出0可以使LED点亮,而ODR复位设置是0x00000000;所以,如果想要使某一个LED点亮,需要先全部置1,然后使用位运算;或者直接用立即数赋值。
我们发现,即使这样,仍然不能点亮LED,这是因为,APB2挂接在AHB,AHB基地址一般认为是0x40020000,AHB上有RCC时钟,其中APB2 外设时钟使能寄存器(RCC_APB2ENR)的偏移是0x18;复位是0x00000000;所以需要对GPIO的C端口的时钟打开,如图,需要将第4位置1,
在这里插入图片描述
代码如下:
一种是直接操作寄存器地址,另一种是通过寄存器映射来实现;

void SystemInit()
{
}

#if 0
//直接操作地址
int main()
{
//打开GPIOC的时钟
	*(unsigned int *)0x40021018 |=((1)<<4);
//配置IO口为输出
	*(unsigned int *)0x40011004 =0x11111111;

//控制ODR寄存器					  
	*(unsigned int *)0x4001100C =0xFEFF;
}

void SystemInit()
{
}
#endif

 //使用寄存器映射

//外设
#define PERIPH_BASE        ((unsigned int)0x40000000)
//总线
#define APB1PERIPH_BASE    PERIPH_BASE 
#define APB2PERIPH_BASE    (PERIPH_BASE+0X10000)
#define AHBPERIPH_BASE     (PERIPH_BASE+0X20000)

//寄存器组
#define RCC_BASE 			 (AHBPERIPH_BASE+0X1000)
#define GPIOC_BASE 		 (APB2PERIPH_BASE+0X1000)

//寄存器
#define RCC_APB2ENR 		 *(unsigned int *)(RCC_BASE+0X18)
#define GPIOC_CRL 		 *(unsigned int *)(GPIOC_BASE+0X00)
#define GPIOC_CRH 		 *(unsigned int *)(GPIOC_BASE+0X04)
#define GPIOC_ODR 		 *(unsigned int *)(GPIOC_BASE+0X0C)
int main()
{
//打开GPIOC的时钟
	RCC_APB2ENR |=((1)<<4);
//配置IO口为输出
	GPIOC_CRH =0x11111111;

//控制ODR寄存器					  
	GPIOC_ODR =0xFEFF;

}

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
驱动RT12864-1液晶屏需要使用STM32F103芯片的GPIO进行控制。以下是一个简单的驱动程序,可供参考: ```c #include "stm32f10x.h" #include "delay.h" // 定义液晶屏接口 #define LCD_EN_CLK RCC_APB2Periph_GPIOA #define LCD_EN_PORT GPIOA #define LCD_EN_PIN GPIO_Pin_6 #define LCD_RS_CLK RCC_APB2Periph_GPIOA #define LCD_RS_PORT GPIOA #define LCD_RS_PIN GPIO_Pin_5 #define LCD_RW_CLK RCC_APB2Periph_GPIOA #define LCD_RW_PORT GPIOA #define LCD_RW_PIN GPIO_Pin_4 #define LCD_DATA_CLK RCC_APB2Periph_GPIOB #define LCD_DATA_PORT GPIOB #define LCD_D0_PIN GPIO_Pin_0 #define LCD_D1_PIN GPIO_Pin_1 #define LCD_D2_PIN GPIO_Pin_2 #define LCD_D3_PIN GPIO_Pin_3 #define LCD_D4_PIN GPIO_Pin_4 #define LCD_D5_PIN GPIO_Pin_5 #define LCD_D6_PIN GPIO_Pin_6 #define LCD_D7_PIN GPIO_Pin_7 // 定义液晶屏命令 #define LCD_CLR 0x01 #define LCD_HOME 0x02 #define LCD_MODE 0x06 #define LCD_DISP 0x0C #define LCD_CURS 0x0E #define LCD_CURS_BL 0x0F #define LCD_FUNC 0x38 // 定义液晶屏函数 void lcd_init(void); void lcd_cmd(uint8_t cmd); void lcd_data(uint8_t data); void lcd_puts(char *str); void lcd_gotoxy(uint8_t x, uint8_t y); int main(void) { // 始化时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE); // 始化液晶屏 lcd_init(); // 显示字符串 lcd_puts("Hello, world!"); while (1) { // 循环执行 } } // 始化液晶屏 void lcd_init(void) { // 始化液晶屏接口 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = LCD_EN_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(LCD_EN_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = LCD_RS_PIN; GPIO_Init(LCD_RS_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = LCD_RW_PIN; GPIO_Init(LCD_RW_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = LCD_D0_PIN | LCD_D1_PIN | LCD_D2_PIN | LCD_D3_PIN | LCD_D4_PIN | LCD_D5_PIN | LCD_D6_PIN | LCD_D7_PIN; GPIO_Init(LCD_DATA_PORT, &GPIO_InitStructure); // 始化液晶屏 delay_ms(20); lcd_cmd(0x30); delay_ms(5); lcd_cmd(0x30); delay_ms(1); lcd_cmd(0x30); lcd_cmd(0x02); lcd_cmd(LCD_FUNC); lcd_cmd(LCD_DISP); lcd_cmd(LCD_CLR); lcd_cmd(LCD_MODE); } // 发送命令到液晶屏 void lcd_cmd(uint8_t cmd) { GPIO_ResetBits(LCD_RS_PORT, LCD_RS_PIN); GPIO_ResetBits(LCD_RW_PORT, LCD_RW_PIN); GPIO_Write(LCD_DATA_PORT, cmd); GPIO_SetBits(LCD_EN_PORT, LCD_EN_PIN); delay_us(10); GPIO_ResetBits(LCD_EN_PORT, LCD_EN_PIN); delay_ms(2); } // 发送数据到液晶屏 void lcd_data(uint8_t data) { GPIO_SetBits(LCD_RS_PORT, LCD_RS_PIN); GPIO_ResetBits(LCD_RW_PORT, LCD_RW_PIN); GPIO_Write(LCD_DATA_PORT, data); GPIO_SetBits(LCD_EN_PORT, LCD_EN_PIN); delay_us(10); GPIO_ResetBits(LCD_EN_PORT, LCD_EN_PIN); delay_ms(2); } // 显示字符串 void lcd_puts(char *str) { while (*str) { lcd_data(*str++); } } // 光标移动到指定位置 void lcd_gotoxy(uint8_t x, uint8_t y) { uint8_t addr; if (y == 0) { addr = 0x80 + x; } else { addr = 0xC0 + x; } lcd_cmd(addr); } ``` 需要注意的是,以上代码仅供参考,具体实现可能需要根据液晶屏型号和引脚分配进行调整。同时,为了保证液晶屏的稳定性,还需要进行一定的始化和延时操作。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值