当前位置: 首页 > news >正文

【SWM320】学习使用GPIO

依旧从点灯开始

先看原理图,C_ELC0和C_ELC1是连接在M2和B12,继电器是常开,1、2号脚就是低压侧,3、4号脚就是开关

继电器是一种低压控制高压的元器件。

低压侧,是一个电磁铁;高压侧,是一个开关,开关上面有弹簧,默认是断开的。

低压侧,电磁铁通电,就会吸引高压侧的永磁铁使开关闭合。

也就是当ELC_0为高电平时,螺旋管的电流导致磁铁通电使开关闭合;当ELC_0为低电平时,没有电流,电磁铁不通电

法一,可以更好了解寄存器

我现在要写实现引脚的函数,要知道引脚的地址,就得查数据手册

我需要B引脚组和M引脚组,我查

我写

//GPIO寄存器基地址 #define Addr_GPIOB_Base (0x40012000) #define Addr_GPIOM_Base (0x40015000) //DATA寄存器 #define Offset_GPIO_DATA (0X00) #define Offset_GPIO_DIR (0X04)

和B引脚组与M引脚组有关的我都先写上

//PORT寄存器基地址 #define Addr_PORT_Base (0x40010000)

先不管后面会不会用得着,我先写上

//SEL寄存器 #define Offset_PORTB_SEL (0X04) #define Offset_PORTM_SEL0 (0X20) #define Offset_PORTM_SEL1 (0X24)

//MUX寄存器 #define Offset_PORTB_MUX0 (0X110) #define Offset_PORTB_MUX1 (0X114) #define Offset_PORTM_MUX0 (0X160) #define Offset_PORTM_MUX1 (0X164) #define Offset_PORTM_MUX2 (0X168) #define Offset_PORTM_MUX3 (0X16C)

//INEN寄存器 #define Offset_PORTB_INEN (0X610) #define Offset_PORTM_INEN (0X640)

以上都是基地址和偏移量分开写,现在该加到一块了,直接得出引脚B组和引脚M组

#define rPORTB_SEL (*(volatile unsigned int*) (Addr_PORT_Base + Offset_PORTB_SEL) ) #define rPORTM_SEL0 (*(volatile unsigned int*) (Addr_PORT_Base + Offset_PORTM_SEL0) ) #define rPORTM_SEL1 (*(volatile unsigned int*) (Addr_PORT_Base + Offset_PORTM_SEL1) ) #define rGPIOB_DATA (*(volatile unsigned int*) (Addr_GPIOB_Base + Offset_GPIO_DATA) ) #define rGPIOB_DIR (*(volatile unsigned int*) (Addr_GPIOB_Base + Offset_GPIO_DIR) ) #define rGPIOM_DATA (*(volatile unsigned int*) (Addr_GPIOM_Base + Offset_GPIO_DATA) ) #define rGPIOM_DIR (*(volatile unsigned int*) (Addr_GPIOM_Base + Offset_GPIO_DIR) )

(*(volatile unsigned int*) (Addr_PORT_Base + Offset_PORTB_SEL))

^ ^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

│ │ │

│ │ └─ 1. 计算地址

│ └─ 2. 强制类型转换

└─ 3. 解引用

有了这些宏之后,就可以编程初始化引脚为GPIO输出功能了:

我要写一个gpio_init_out函数,配置好PM2和PB12两个引脚

配置PB12:

rPORTB_SEL &= ~(3<<24);

配置PM2

rPORTM_SEL0 &= ~(3<<4);

设置引脚为输出(置1为输出)

rGPIOB_DIR |= (1<<12);

rGPIOM_DIR |= (1<<2 );

关闭输入使能

rPORTB_INEN &= ~(1<<12);

rPORTM_INEN &= ~(1<<2);

给PB12和PM2高电平(写1)

rGPIOB_DATA |= (1<<12); //GPIO B12输出高电平
rGPIOM_DATA |= (1<<2 ); //GPIO M2 输出高电平

此函数完整版:

void gpio_init_out(void) { //<1>将引脚的基本属性设置为GPIO:B12和M2 设置功能为00 rPORTB_SEL &= ~(3<<24); rPORTM_SEL0 &= ~(3<<4); //<2>接通端口数据输出开关 rGPIOB_DIR |= (1<<12); rGPIOM_DIR |= (1<<2 ); //<3>关闭端口数据输入开关 rPORTB_INEN &= ~(1<<12); rPORTM_INEN &= ~(1<<2); //<4>往端口引脚写数据,实现输出指定电平值 rGPIOB_DATA |= (1<<12); //GPIO B12输出高电平 rGPIOM_DATA |= (1<<2 ); //GPIO M2 输出高电平 }

发现不起作用?我们用到了PORTB外设和PORTM外设,所有外设在使用前,都要先给外设提供时钟,修改gpio_init_out()函数,先使能外设时钟,再初始化

系统时钟基地址和使能偏移量

#define Addr_SYSCON_Base 0x40000000 #define Offset_SYS_CLKEN (0x08) #define rSYS_CLKEN ( *(volatile unsigned int*)( Addr_SYSCON_Base + Offset_SYS_CLKEN ) )

使能B组和M组

//使能外设时钟 B M rSYS_CLKEN |= (1<<1); rSYS_CLKEN |= (1<<4);

所以,完整版应该是:

#define Addr_SYSCON_Base 0x40000000 #define Offset_SYS_CLKEN (0x08) #define rSYS_CLKEN ( *(volatile unsigned int*)( Addr_SYSCON_Base + Offset_SYS_CLKEN ) ) void gpio_init_out(void) { //使能外设时钟 B M rSYS_CLKEN |= (1<<1); rSYS_CLKEN |= (1<<4); //<1>将引脚的基本属性设置为GPIO:B12和M2 设置功能为00 rPORTB_SEL &= ~(3<<24); rPORTM_SEL0 &= ~(3<<4); //<2>接通端口数据输出开关 rGPIOB_DIR |= (1<<12); rGPIOM_DIR |= (1<<2 ); //<3>关闭端口数据输入开关 rPORTB_INEN &= ~(1<<12); rPORTM_INEN &= ~(1<<2); //<4>往端口引脚写数据,实现输出指定电平值 rGPIOB_DATA |= (1<<12); //GPIO B12输出高电平 rGPIOM_DATA |= (1<<2 ); //GPIO M2 输出高电平 }

也可以加上延时

void delay_some_time(void) { volatile uint32_t d= 0; d = 10000000; while(d--); }

和led_ctrl函数

void led_ctrl( int pwr ) { if( 0 == pwr ) { rGPIOB_DATA &= ~(1<<12); //B12输出低电平 rGPIOM_DATA &= ~(1<<2 ); //M2 输出低电平 } else { rGPIOB_DATA |= (1<<12); //B12输出高电平 rGPIOM_DATA |= (1<<2 ); //M2 输出高电平 } }

main函数就为

int main(void) { uint32_t chr; uint32_t err; SystemInit(); SerialInit(); printf("hello swm320\r\n"); printf("cpu:%d\r\n",SystemCoreClock); //编程让某些引脚输出高电平 ELC0 M2 / ELC1 B12 gpio_init_out( 0 ); while(1==1) { led_ctrl( 1 ); delay_some_time(); led_ctrl( 0 ); delay_some_time(); } }

法二,使用官方SDK编程

void led_ctrl( int pwr ) { if( 0 == pwr ) { GPIO_ClrBit(GPIOB, PIN12); //设置输出0 GPIO_ClrBit(GPIOM, PIN2 ); //设置输出0 } else { GPIO_SetBit(GPIOB, PIN12); //设置输出1 GPIO_SetBit(GPIOM, PIN2 ); //设置输出1 } } void delay_some_time(void) { volatile uint32_t d= 0; d = 10000000; while(d--); } int main(void) { SystemInit(); //初始化B12 M2为输出功能 GPIO_Init(GPIOB, PIN12, 1, 0, 0); //输出, 接LED GPIO_Init(GPIOM, PIN2 , 1, 0, 0); //输出, 接LED while(1==1) { led_ctrl( 1 ); delay_some_time(); led_ctrl( 0 ); delay_some_time(); } }
http://www.jsqmd.com/news/491552/

相关文章:

  • 华为OD机考双机位C卷 - 智能驾驶(Java Python JS GO C++ C)
  • 利用omnicoder-9b模型编写把扫描版pdf转成文字版pdf的程序
  • 六轴机械臂的轨迹优化就像在迷宫里找最短路线——传统粒子群算法(PSO)容易卡在局部最优里打转。咱们今天搞点野路子,给算法加点特技
  • DVWA 搭建踩坑全记录:卡在 “Invalid database selected” 最后一关(新手求助!Help)
  • GitHub 热榜 Top 10 (316) ​
  • 2026年全屋定制应用白皮书南京装修权威厂家解析 - 优质品牌商家
  • Day01笔记整理
  • 【个人量化必备】:A股全市场5000+股票实时行情获取
  • 受激发射损耗(STED)显微镜
  • CSE-CIC-IDS2018数据集获取
  • VOOHU 沃虎电子_10G Base-T 网络变压器 WHSM24P03-2PG 解决超高清视频传输供电难题
  • 计算机毕业设计之springboot北工国际健身俱乐部
  • AI原生应用领域意图识别的发展现状与未来展望
  • Hexo Butterfly 主题副标题不显示问题解决方案
  • 0 Basic Study Java Day01
  • Winform Modbus 316线程 异步 λ表达式 泛型与数组 Encoding.ASCII.GetBytes bitConverter 大端小端 寄存器与label
  • 大模型连载8:词向量如何表示近义词?
  • VScode快捷键
  • 2026年国标减压阀厂家推荐:煤气阀/液化气减压阀/大火力减压阀/汀鸥减压阀供应企业推荐 - 品牌推荐官
  • 2026年锅炉除氧器厂家专业选型参考:真空/大气式/热力/余热锅炉除氧器供应商推荐 - 品牌推荐官
  • 在idea中配置maven本地仓库
  • 239 滑动窗口最大值
  • gpt-claude-gemini稳定api代理
  • 进程间通信(IPC)- 管道专题学习笔记
  • 小白从零开始勇闯人工智能:LangChain 入门指南(下)
  • GoChatIAI -Go语言AI应用服务平台(3)
  • 酒店地毯供应商实力评测及选购指南 - 优质品牌商家
  • 6款思维导图软件深度评测:协作、AI能力与工具选型对比
  • 基于javaweb和mysql的ssm酒吧后台管理系统(java+ssm+jsp+html+mysql)
  • ToB/ToC 前端开发:程序员选赛道必看!从业务本质到技术选型,避开高频坑