LK32T102学习2-GPIO

本文围绕LK32T102单片机的GPIO功能展开,介绍了GPIO口可实现多种功能,掌握它是MCU编程入门关键。阐述了GPIO功能使用注意事项、口使用步骤,还给出流水灯、按键、LCD液晶显示屏等实例,最后提及后续学习方向及交流群。

GPIO即可编程输入输出口,LK32T102有3组GPIO口,每组最多32条口线。GPIO口线可以实现很多的功能,可以说掌握了GPIO功能也就MCU编程也就基本实现了MCU的入门。

GPIO功能使用

要注意LTK320T的管脚是多功能的,可作为数字量管脚,也可以作为模拟量管脚。

输入模式浮空输入模式输入完全由外部输入决定PU,PD都不导通
上拉输入模式IO悬空时输入为高电平PU导通,PD不导通
下拉输入模式IO悬空时输入为低电平PU不导通,PD导通
模拟输入模式接模拟信号无特殊要求
输出模式开漏输出模式
开漏复用输出模式
推挽输出模式
推挽复用输出模式

首先涉及到管脚功能的选择,涉及到多个寄存器,主要涉及:

*清零和置位本质上是通过两个地址来控制物理上的一个寄存器,使得每一位都可以独立修改,而无需担心在两个进程竞争访问过程时出现的数据丢失(?)--<<ARM Cortex-M0权威指南(中文版)>>P127

为简化操作,模板中提供了很多函数及宏,主要声明在gpio.h,函数实现在gpio.c

void GPIO_AF_SEL(uint8_t AD,PA_Type* GPIOx,uint8_t gpiopin,uint8_t fun_num)设定管脚功能AD:  DIGITAL   ANALOGY数字管脚功能还是模拟管脚功能
GPIOx:PA,PB,PC那一组管脚
gpiopin:0~31管脚号
fun_num:0~7功能号
void GPIO_OD_SEL(uint8_t OD,PA_Type* GPIOx,uint8_t gpiopin);
void GPIO_DRV_SEL(uint8_t DRV,PA_Type* GPIOx,uint8_t gpiopin);
 void GPIO_PUPD_SEL(uint8_t PUPD,PA_Type* GPIOx,uint8_t gpiopin);
void GPIO_Init()管脚初始化主函数main中调用了Device_Init();而Device_Init()又调用了GPIO_Init(),此函数我们根据需要修改,主要调用GPIO_AF_SEL
功能直接操作寄存器备注
输出功能宏PA_OUT_ENABLE(x)输出使能PA -> OUTEN |= (1 << x);以PA为例,其他类似,也可以直接操作寄存器
 PA_OUT_DISABLE(x)输出不能PA -> OUTEN &= ~(1<<x);    
PA_OUT_HIGH(x)输出高PA -> OUTSET = (1<<x);
PA_OUT_LOW(x)输出低PA -> OUTCLR = (1<<x);
PA_OUT_TOGGLE(x)输出反转PA->OUTTGL = (1<<x);
中断功能宏PA_INT_ENABLE(x)中断使能PA->INTMASK&=~(1<<x);    
PA_INT_DISABLE(x)中断屏蔽PA->INTMASK|=(1<<x);    
PA_INT_LEVEL(x)电平触发PA->INTTYPE&=~(1<<x);
PA_INT_EDGE(x)边沿触发PA->INTTYPE|=(1<<x);    
PA_INT_BE_ENABLE(x)双边沿触发PA->INTBV|=(1<<x);    
PA_INT_BE_DISABLE(x)单边沿触发PA->INTBV&=~(1<<x);
PA_INT_POL_HIGH(x)上升沿或高电平触发PA->INTPOL|=(1<<x);
PA_INT_POL_LOW(x)下升沿或低电平触发PA->INTPOL&=~(1<<x);    
PA_INT_FLAG_CLR(x)中断标志清除PA->RIS=(1<<x);
/*
 实现PA0输出高电平
*/
GPIO_AF_SEL(DIGITAL,PA,0,0);//设置管脚PA0为数字功能选择,且为GPIO功能
PA_OUT_ENABLE(0);//PA0输出使能
PA_OUT_HIGHT(0);

GPIO口使用步骤:

1.选择管脚,设定管脚功能

GPIO_AF_SEL();

2.设定GPIO输出方向

1).使能GPIO输出

Pn_OUT_ENABLE(x);//(n=A,B,C)

2)使能GPIO输入

Pn_OUT_DISABLE(x);//(n=A,B,C)

3.设定管脚值

1)设定输出高电平

Pn_OUT_HIGH(x);//(n=A,B,C)

2)设定输出低电平

Pn_OUT_LOW(x);//(n=A,B,C)

3)设定高低电平

Pn->OUT=x;//(n=A,B,C)

4.判断管脚值的高低

1)判断x管脚是否为高(n=A,B,C)

(Pn->PIN&(1<<x))!=0

2)判断x管脚是否为低(n=A,B,C)

(Pn->PIN&(1<<x))==0

5.获取管脚值(n=A,B,C x=0~15)

Px->PIN_b.INx

实例

1.流水灯 

/*
实现流水灯
*/
//一定需要的2个头文件
#include <SC32F5832.h>
#include <DevInit.h>
//使用模板才需要的头文件
#include "keyboard4x4.h"
#include "delay.h"
#include "UART.h"
#include "printf.h"
#include "ds18b20.h"
#include "LCD12864.h"
#include "segment.h"
#include "motor.h"
//流水灯的花型数据
unsigned char table[]={(1<<0),(1<<1),(1<<2),(1<<3),(1<<4),(1<<5),(1<<6),(1<<7),};
int main(void){
    int i=0;
    //设备初始化
   	Device_Init();//Device_Init()主要用到其中的管脚功能选择,也可以在GPIO_Init函数中修改
                  //也可以直接操作寄存器,不用此函数,但是会比较麻烦
	PB -> OUTEN |=0x00ff;//直接操作寄存器,使选定的管脚可以输出,亦可以直接用8个宏PA_OUT_ENABLE(x)
	
	while(1){
		for(i=0;i<sizeof(table)/sizeof(char);i++){
          //熄灭8个LED
		  PB -> OUTSET=0X00FF;//输出8个高电平,或其他的PA口管脚不受到影响
                               //亦可以用8个PA_OUT_HIGH(x)
     	  delay_ms(2000);
          //点亮8个LED
		  PB ->OUTCLR =table[i];//输出8个低电平,其他的PA口管脚不受到影响
                                 //亦可以用8个PA_OUT_LOW(x)
		  delay_ms(2000);
		}
	}	
}
	

2.板上按键

/*
按下核心板上SB1~SB4,相应的核心板上LED1~LED4点亮,释放按键,相应的LED0~LED3熄灭
*/
//一定需要的2个头文件
#include <SC32F5832.h>
#include <DevInit.h>
//使用模板才需要的头文件
#include "keyboard4x4.h"
#include "delay.h"
#include "UART.h"
#include "printf.h"
#include "ds18b20.h"
#include "LCD12864.h"
#include "segment.h"
#include "motor.h"
//流水灯的花型数据
unsigned char table[]={(1<<0),(1<<1),(1<<2),(1<<3),(1<<4),(1<<5),(1<<6),(1<<7),};
int main(void){
    int i=0;
    //设备初始化
   	Device_Init();//Device_Init()主要用到其中的管脚功能选择,也可以在GPIO_Init函数中修改
                  //也可以直接操作寄存器,不用此函数,但是会比较麻烦
	PB -> OUTEN |=0x00ff;//直接操作寄存器,使选定的管脚可以输出,亦可以直接用8个宏PA_OUT_ENABLE(x)
	
	while(1){
		if((PA->PIN&(1<<0))==0){//SB1按下
              PB->OUTCLR=1<<0;//点亮灯LED1
         }else{
              PB->OUTSET=1<<0;//熄灭灯LED1
         }

		if((PA->PIN&(1<<1))==0){//SB2按下
              PB->OUTCLR=1<<1;//点亮灯LED2
         }else{
              PB->OUTSET=1<<1;//熄灭灯LED2
         }

		if((PA->PIN&(1<<10))==0){//SB3按下
              PB->OUTCLR=1<<10;//点亮灯LED3
         }else{
              PB->OUTSET=1<<10;//熄灭灯LED3
         }

		if((PA->PIN&(1<<11))==0){//SB4按下
              PB->OUTCLR=1<<11;//点亮灯LED4
         }else{
              PB->OUTSET=1<<11;//熄灭灯LED4
         }
	}	
}
	

注意在提供的例程其keyboard4x4.c中实现了核心板的键功能,疑似有问题,不要使用,如需使用核心板上的按键请按上述代码实现。

3.扩展板操作的矩阵式按键

扩展板是一个4X4的矩阵式按键。

矩阵式按键可以操作更多按键,其实质也是GPIO口的操作。

对于提供的模板来说,已经实现了操作代码,其以PB口来实现,如果需要改变接线需要修改keyboard4x4.c的uint8_t scan_MatrixKey( void ),并修改gpio.c中的GPIO_Init()中的有关配置,设置相应的管脚为GPIO口。示例中其在GPIO_Init中已经进行了配置,在keyboard4x4.c中实现了功能,一般可以直接调用。

scan_MatrixKey用行反转法识别按键。

/*
按下扩展板上按键,相应的核心板上LED点亮或蜂鸣器响
*/
//一定需要的2个头文件
#include <SC32F5832.h>
#include <DevInit.h>
//使用模板才需要的头文件
#include "keyboard4x4.h"
#include "delay.h"
#include "UART.h"
#include "printf.h"
#include "ds18b20.h"
#include "LCD12864.h"
#include "segment.h"
#include "motor.h"
/**
	* @param  SC32F5832 -> KeyBoard 
	*							PB8 	-> 	CN3-R1
	*							PB9 	-> 	CN3-R2
	*							PB10 	-> 	CN3-R3
	*							PB11 	-> 	CN3-R4
	*							PB12 	-> 	CN3-C1
	*							PB13 	-> 	CN3-C2
	*							PB14 	-> 	CN3-C3
	*							PB15 	-> 	CN3-C4
*/
/*#define---------------------------------------------------------------------*/
#define BUZZER_OFF 	PA -> OUTSET = (1 << 12)  //蜂鸣器响
#define BUZZER_ON 	PA -> OUTCLR = (1 << 12)  //蜂鸣器关断


#define LED1_ON PB -> OUTCLR = (1 << 0)//PB0 -D9  输出低电平,LED1亮
#define LED2_ON PB -> OUTCLR = (1 << 1)//PB0 -D10 输出低电平,LED2亮
#define LED3_ON PB -> OUTCLR = (1 << 2)//PB0 -D11 输出低电平,LED3亮
#define LED4_ON PB -> OUTCLR = (1 << 3)//PB0 -D12 输出低电平,LED4亮
#define LED5_ON PB -> OUTCLR = (1 << 4)//PB0 -D14 输出低电平,LED5亮
#define LED6_ON PB -> OUTCLR = (1 << 5)//PB0 -D15 输出低电平,LED6亮
#define LED7_ON PB -> OUTCLR = (1 << 6)//PB0 -D16 输出低电平,LED7亮
#define LED8_ON PB -> OUTCLR = (1 << 7)//PB0 -D17 输出低电平,LED8亮

#define LED1_OFF PB -> OUTSET = (1 << 0)//PB0 -D9  输出高电平,LED1灭
#define LED2_OFF PB -> OUTSET = (1 << 1)//PB0 -D10 输出高电平,LED2灭
#define LED3_OFF PB -> OUTSET = (1 << 2)//PB0 -D11 输出高电平,LED3灭
#define LED4_OFF PB -> OUTSET = (1 << 3)//PB0 -D12 输出高电平,LED4灭
#define LED5_OFF PB -> OUTSET = (1 << 4)//PB0 -D14 输出高电平,LED5灭
#define LED6_OFF PB -> OUTSET = (1 << 5)//PB0 -D15 输出高电平,LED6灭
#define LED7_OFF PB -> OUTSET = (1 << 6)//PB0 -D16 输出高电平,LED7灭
#define LED8_OFF PB -> OUTSET = (1 << 7)//PB0 -D17 输出高电平,LED8灭
int main()
{
	
	Device_Init();	
	
		
	PB -> OUTEN |= 0xff;//PB0~PB7,输出,控制LED
                          //PB8~PB15,一半输入,一半输出,控制矩阵式按键
	PB -> OUT |= 0xffff;//PB0~PB15全输出高电平
	
	PA_OUT_ENABLE(12); //核心板蜂鸣器管脚使能
	BUZZER_OFF;        //蜂鸣器关断
	
	
	while(1)
	{

		i = scan_MatrixKey();//读取矩阵式按键键值
		
		if(1 == i)		//按键1按下
			LED1_ON;//LED1亮
		else
			LED1_OFF;
		
		if(5 == i)		//按键5按下
			LED2_ON;//LED2亮
		else
			LED2_OFF;

		if(9 == i )		//按键9按下
			LED3_ON;//LED3亮
		else
			LED3_OFF;
		
		if(13 == i )	//按键13按下
			BUZZER_ON;//蜂鸣器响
		else
			BUZZER_OFF;//蜂鸣器关断

	}
	
}

4扩展板的LCD液晶显示屏操作:

扩展板上的LCD12864是带中文字库的128X64点阵图形液晶显示模块,可以显示8×4 行16×16 点 阵的汉字。

其实质也是GPIO操作,其用GPIO口模拟实现液晶电路的接口操作。

对于提供的模板来说,已经实现了操作代码,其以PC口来实现。如果需要改变接线,修改的内容较多,一般可以直接调用。

/*
LCD显示实验
*/
//一定需要的2个头文件
#include <SC32F5832.h>
#include <DevInit.h>
//使用模板才需要的头文件
#include "keyboard4x4.h"
#include "delay.h"
#include "UART.h"
#include "printf.h"
#include "ds18b20.h"
#include "LCD12864.h"
#include "segment.h"
#include "motor.h"
#define BUZZER_OFF 	PA -> OUTSET = (1 << 12)  //蜂鸣器响
#define BUZZER_ON 	PA -> OUTCLR = (1 << 12)  //蜂鸣器关断
/**
	* @brief  LCD12864接线
	* @param  SC32F5832 -> LCD12864
	*							PC6 	-> 	CN3-RS
	*							PC4 	-> 	CN3-RW
	*							PC3 	-> 	CN3-E
	*							PC7 	-> 	CN3-PSB
	*							PC15 	-> 	CN3-RST
*/
int main( void )
{
	
	Device_Init();
	
   //LCD12864============================
	delay_ms(500);	
	LCD_GPIO_Init();//LCD12864 GPIO初始化
	PSB_0;
	CS_1;
    lcd_init();//LCD12864初始化
		
    delay_ms(100);
	lcd_clear();//清屏
	delay_ms(100);
	
  
    lcd_wstr(2, 0, "例程");//
    lcd_wstr(2,7,"15℃");
	
	
	write_figer(2,5,1234);
	
	
	BUZZER_OFF;
//LCD12864============================	
	
	while(1);
	
	
}

上述的例程可以直接套用,在需要显示的时候可以直接调用,我们主要涉及到void lcd_wstr(uint8_t y_add , uint8_t x_add , char *str)  和void write_figer(uint8_t y_add, uint8_t x_add, uint32_t figer)

lcd_wstr实现了在y_add行,x_add位置开始写了1个字符串str,而write_figer实现了在y_add行,x_add位置开始写了1个特殊格式的浮点数.。建议直接使用sprintf函数将浮点数变为字符串

#include“stdio.h”
int main(){
  float f=3.1415;
  char buff[10];
  sprintf(buff,"%f",f)
  printf("the result=%s",buff);
  return 1;
}

示例中似乎有瑕疵

5.扩展板的数码管

温度测量扩展板上的数码管是GPIO应用的一个例子。

/*
温度扩展板上数码管显示1234
*/
//一定需要的2个头文件
#include <SC32F5832.h>
#include <DevInit.h>
//使用模板才需要的头文件
#include "keyboard4x4.h"
#include "delay.h"
#include "UART.h"
#include "printf.h"
#include "ds18b20.h"
#include "LCD12864.h"
#include "segment.h"
#include "motor.h"
/** @brief:温度测量扩展板的接线说明
	*							PB8 	-> 	pa
	*							PB9 	-> 	pb
	*							PB10 	-> 	pc
	*							PB11	-> 	pd
	*							PB12 	-> 	pe
	*							PB13 	-> 	pf
	*							PB14 	-> 	pg
	*							PB15 	-> 	dp
	*	
	*							PA4 	-> 	74LS138-A0
	*							PA5 	-> 	74LS138-A1
	*							PA6 	-> 	74LS138-A2
	*
*/
int main( void )
{
   
	
	Device_Init();
	SEG_GPIO_Init();

	while(1){
        Dispaly_Number( 0, 1 );
		ST_delay_ms( 2 );
		Dispaly_Number( 1, 2 );
		ST_delay_ms( 2 );
		Dispaly_Number( 2, 3 );
		ST_delay_ms( 2 );
		Dispaly_Number( 3, 4 );
		ST_delay_ms( 2 );
		Dispaly_Number( 10, 3 );	
   }
}

在利用模块的时候发现有问题, 

6.扩展板的DS18B20

温度测量扩展板上的DS18B20是一种单总线的数字式测温传感器,MCU只需要一个GPIO口线就可以和其通信,对其进行控制。下面的实验将测量的温度显示在lcd上

/*
LCD显示实验
*/
//一定需要的2个头文件
#include <SC32F5832.h>
#include <DevInit.h>
//使用模板才需要的头文件
#include "keyboard4x4.h"
#include "delay.h"
#include "UART.h"
#include "printf.h"
#include "ds18b20.h"
#include "LCD12864.h"
#include "segment.h"
#include "motor.h"
#define BUZZER_OFF 	PA -> OUTSET = (1 << 12)  //蜂鸣器响
#define BUZZER_ON 	PA -> OUTCLR = (1 << 12)  //蜂鸣器关断
/**
	* @brief  LCD12864接线说明
	* @param  SC32F5832 -> LCD12864
	*							PC6 	-> 	CN3-RS
	*							PC4 	-> 	CN3-RW
	*							PC3 	-> 	CN3-E
	*							PC7 	-> 	CN3-PSB
	*							PC15 	-> 	CN3-RST
*/
	/**
	* @brief  单总线温度传感器接线说明
	* @param  SC32F5832 -> 温度传感器模块
	*							PA15 	-> 	CN2-DSO
	*/

int main( void )
{
	
	Device_Init();

	PA_OUT_ENABLE(12);//蜂鸣器使能

   //LCD12864============================
	delay_ms(500);	
	LCD_GPIO_Init();//LCD12864 GPIO初始化
	PSB_0;
	CS_1;

    lcd_init();//LCD12864初始化
    delay_ms(100);

	lcd_clear();//清屏
	delay_ms(100);
  
    lcd_wstr(2, 0, "例程");//
    lcd_wstr(2,7,"15℃");
	
	
	BUZZER_OFF;

	while(1){
		//工作显示		
		LED1_ON;
		ST_delay_ms(500);
		LED1_OFF;
		ST_delay_ms(500);
				
		//DS18B20 温度采集
		DS18B20_Temp = DS18B20_Get_Temp();
		//LCD 数据显示
		write_figer(2,4,DS18B20_Temp);
    }
}

ps:

学会了这部分内容已经完成大部分任务了,下面就是中断、定时计数器、AD及PWM

/***********************************************************************************************************/

很遗憾,有很多的东西我没有办法一一给大家回复,所以我建立了一个群,供大家一起交流!

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

和风化雨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值