依旧从点灯开始
先看原理图,C_ELC0和C_ELC1是连接在M2和B12,继电器是常开,1、2号脚就是低压侧,3、4号脚就是开关
继电器是一种低压控制高压的元器件。
低压侧,是一个电磁铁;高压侧,是一个开关,开关上面有弹簧,默认是断开的。
低压侧,电磁铁通电,就会吸引高压侧的永磁铁使开关闭合。
也就是当ELC_0为高电平时,螺旋管的电流导致磁铁通电使开关闭合;当ELC_0为低电平时,没有电流,电磁铁不通电



法一,可以更好了解寄存器
我现在要写实现引脚的函数,要知道引脚的地址,就得查数据手册
我需要B引脚组和M引脚组,我查
我写
cpp//GPIO寄存器基地址 #define Addr_GPIOB_Base (0x40012000) #define Addr_GPIOM_Base (0x40015000) //DATA寄存器 #define Offset_GPIO_DATA (0X00) #define Offset_GPIO_DIR (0X04)
和B引脚组与M引脚组有关的我都先写上
cpp//PORT寄存器基地址 #define Addr_PORT_Base (0x40010000)先不管后面会不会用得着,我先写上
cpp//SEL寄存器 #define Offset_PORTB_SEL (0X04) #define Offset_PORTM_SEL0 (0X20) #define Offset_PORTM_SEL1 (0X24)
cpp//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)
cpp//INEN寄存器 #define Offset_PORTB_INEN (0X610) #define Offset_PORTM_INEN (0X640)
以上都是基地址和偏移量分开写,现在该加到一块了,直接得出引脚B组和引脚M组
cpp#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);
配置PM2rPORTM_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 输出高电平
此函数完整版:
cpp
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()函数,先使能外设时钟,再初始化
查系统时钟基地址和使能偏移量
cpp#define Addr_SYSCON_Base 0x40000000 #define Offset_SYS_CLKEN (0x08) #define rSYS_CLKEN ( *(volatile unsigned int*)( Addr_SYSCON_Base + Offset_SYS_CLKEN ) )
使能B组和M组
cpp//使能外设时钟 B M rSYS_CLKEN |= (1<<1); rSYS_CLKEN |= (1<<4);
所以,完整版应该是:
cpp
#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 输出高电平
}
也可以加上延时
cpp
void delay_some_time(void)
{
volatile uint32_t d= 0;
d = 10000000;
while(d--);
}
和led_ctrl函数
cpp
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函数就为
cpp
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编程



cpp
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();
}
}




rPORTB_SEL &= ~(3<<24);




