【CH559单片机 】GPIO输出模式以及GPIO中断介绍以及示例

【CH559单片机 】GPIO输出模式以及外部中断介绍以及示例


  • 📌E8051 USB系列中的CH559单片机.
  • 📍本示例基于官方所提供的的参考示例资料:https://www.wch.cn/products/CH549.html

在这里插入图片描述

🌻GPIO 简介

  • 🌿CH559 提供最多 45 个 I/O 引脚,部分引脚具有复用功能。其中,端口 P0~P3 的输入和输出以及 P4 的输出都可以按位寻址。
  • 🌿如果引脚没有被配置成复用功能,则默认是通用 I/O 引脚状态。作为通用数字 I/O 使用时,所有 I/O 端口都具有真正的“读–修改–写”功能,支持 SETB 或者 CLR 等位操作指令独立地改变某些引脚的方向或者端口电平等。

在这里插入图片描述
在这里插入图片描述

📑端口配置寄存器(PORT_CFG):

在这里插入图片描述

📑Pn 端口输入输出寄存器(Pn):

在这里插入图片描述

📑Pn 端口方向控制寄存器(Pn_DIR):

在这里插入图片描述

📑P0 端口上拉使能寄存器(P0_PU)和 Pn 端口上拉使能寄存器(Pn_PU),此处 n=1/2/3:

在这里插入图片描述

🧾由 PORT_CFG 中的位 bPn_OC 和端口方向控制寄存器 Pn_DIR 以及端口上拉使能寄存器 Pn_PU 组合

实现 Pn 端口的相关配置,具体如下。
在这里插入图片描述

  • 🍭P0~P3 端口支持纯输入或推挽输出以及准双向等模式,P4 端口支持纯输入或推挽输出等模式。
  • 🍭各引脚都有可以自由控制的连接到 VDD33 的内部上拉电阻,以及都有连接到 GND 的保护二极管。
  • 🍭图 10.2.1 是 P1 端口的 P1.x 引脚的等效原理图,去掉 P1_IE 和 AIN 以及 ADC_CHANN 之后可以适用于 P0、P2、P3 端口。

在这里插入图片描述
在这里插入图片描述

🎯GPIO总结的配置寄存器表

在这里插入图片描述

⛳CH559中断向量表

在这里插入图片描述
在这里插入图片描述

📝中断相关寄存器列表在这里插入图片描述

✒中断使能寄存器(IE)

在这里插入图片描述

🧧扩展中断使能寄存器(IE_EX):

在这里插入图片描述

📗GPIO 中断使能寄存器(GPIO_IE):

在这里插入图片描述
在这里插入图片描述

⏳中断优先级控制寄存器(IP):

在这里插入图片描述

⌚扩展中断优先级控制寄存器(IP_EX):

在这里插入图片描述
在这里插入图片描述

📢在CH559单片机中数据类型注意事项

- 定义的返回值数据类型为UINT8的函数不能用UINT8类型的变量来接收。

👉这个坑,需要注意,写着是8位增强型单片机,但是实际上运行是以16位的数据总线宽度。
在这里插入图片描述

  • 👉例如端口0、1、2、3引脚模式设置
UINT8 CH559GPIOModeSelt(UINT8 Port,UINT8 Mode,UINT8 PinNum)
{
  UINT8 Pn_DIR,Pn_PU;
	if(Port >= 4){
		return 0;
	}

  switch (Mode){
    	case 0:                                                                //仅输入,无上拉
    		PORT_CFG &= ~(bP0_OC << Port);//11111101
    		Pn_DIR &= ~(1<<PinNum);
    		Pn_PU &= ~(1<<PinNum);
    		break;
    	case 1:                                                                //仅输入,带上拉
    		PORT_CFG &= ~(bP0_OC << Port);
    		Pn_DIR &= ~(1<<PinNum);
    		Pn_PU |= 1<<PinNum;
    		break;
    	case 2:                                                                //推挽输出,高低电平强驱动
    		PORT_CFG &= ~(bP0_OC << Port);
    		Pn_DIR |= (1<<PinNum);
    		break;
    	case 3:                                                                //开漏输出,无上拉,支持输入
    		PORT_CFG |= (bP0_OC << Port);
    		Pn_DIR &= ~(1<<PinNum);
    		Pn_PU &= ~(1<<PinNum);
    		break;
    	case 4:                                                                //开漏输出,无上拉,当转变输出由低到高时,仅驱动2个时钟的高电平
    		PORT_CFG |= (bP0_OC << Port);
    		Pn_DIR |= 1<<PinNum;
    		Pn_PU &= ~(1<<PinNum);
    		break;
    	case 5:                                                                //弱准双向(标准51模式),开漏输出,带上拉
    		PORT_CFG |= (bP0_OC << Port);
    		Pn_DIR &= ~(1<<PinNum);
    		Pn_PU |= 1<<PinNum;
    		break;
    	case 6:                                                                //准双向(标准51模式),开漏输出,带上拉,当转变输出由低到高时,仅驱动2个时钟的高电平
    		PORT_CFG |= (bP0_OC << Port);
    		Pn_DIR |= 1<<PinNum;
    		Pn_PU |= 1<<PinNum;
    		break;
    	default:
    		break;
	}
	if(Port == 0){
		P0_DIR = Pn_DIR;
		P0_PU = Pn_PU;
	}
	if(Port == 1){
		P1_DIR = Pn_DIR;
		P1_PU = Pn_PU;
	}
	if(Port == 2){
		P2_DIR = Pn_DIR;
		P2_PU = Pn_PU;
	}
	if(Port == 3){
		P3_DIR = Pn_DIR;
		P3_PU = Pn_PU;
	}
  return 1;
}
  • 需要定义一个UINT16的变量来接收UINT8函数返回值。
UINT16  value==CH559GPIOModeSelt(2,2,4);//P2端口,推挽模式,P2.4

📝GPIO输出以及GPIO中断示例代码

代码中P14为gpio中断引脚,触发方式:低电平触发,P12和P24设置为了推挽输出模式,


/********************************** (C) COPYRIGHT *******************************
* File Name          : GPIO.C
* Author             : WCH
* Version            : V1.9
* Date               : 2021/12/15
* Description        : CH559的GPIO操作,使用时可以简单操作,直接配置
                       IO配置主要跟一下寄存器的状态有关系
											 bPn_OC & Pn_DIR & Pn_PU: pin input & output configuration for Pn (n=0/1/2/3)
											 详细介绍请看CH559.H的 457行
*******************************************************************************/
#include "..\DEBUG.C"                                                          //调试信息打印
#include "..\DEBUG.H"

sbit led =P1^2;
sbit led2 =P2^4;
sbit led3 =P2^5;




#pragma  NOAREGS

/*******************************************************************************
* Function Name  : CH559GPIODrivCap(UINT8 Port,UINT8 Cap)
* Description    : 端口0、1、2、3驱动能力设置
* Input          : UINT8 Port端口选择(0、1、2、3)
                   UINT8 Cap驱动能力选择((0)5mA、(1)20mA(注意:P1口是10mA))
* Output         : None
* Return         : SUCCESS成功
                   FAIL失败
*******************************************************************************/
UINT8 CH559GPIODrivCap(UINT8 Port,UINT8 Cap)
{
	if(Port >= 4){
		return FAIL;
	}
	if(Cap == 0){ //驱动电流最大5mA
    PORT_CFG &= ~(bP0_DRV << Port);//
  }
  else{		
    PORT_CFG |= (bP0_DRV << Port);//驱动电流最大20mA
  }
  return SUCCESS;
}

/*******************************************************************************
* Function Name  : CH559GPIOModeSelt(UINT8 Port,UINT8 Mode,UINT8 PinNum)
* Description    : 端口0、1、2、3引脚模式设置
* Input          : UINT8 Port端口选择(0、1、2、3)
                   UINT8 Cap驱动方式选择(bPn_OC & Pn_DIR & Pn_PU)
                   0(000):仅输入,无上拉;
                   1(001):仅输入,带上拉;
                   2(01x):推挽输出,高低电平强驱动;
                   3(100):开漏输出,无上拉,支持输入;
                   4(110):开漏输出,无上拉,当转变输出由低到高时,仅驱动2个时钟的高电平
                   5(101):准双向(标准51模式),开漏输出,带上拉
                   6(111):准双向(标准51模式),开漏输出,带上拉,当转变输出由低到高时,仅驱动2个时钟的高电平
                   UINT8 PinNum(引脚选择0-7)
* Output         : None
* Return         : SUCCESS成功
                   FAIL失败
*******************************************************************************/
UINT8 CH559GPIOModeSelt(UINT8 Port,UINT8 Mode,UINT8 PinNum)
{
  UINT8 Pn_DIR,Pn_PU;
	if(Port >= 4){
		return 0;
	}

  switch (Mode){
    	case 0:                                                                //仅输入,无上拉
    		PORT_CFG &= ~(bP0_OC << Port);//11111101
    		Pn_DIR &= ~(1<<PinNum);
    		Pn_PU &= ~(1<<PinNum);
    		break;
    	case 1:                                                                //仅输入,带上拉
    		PORT_CFG &= ~(bP0_OC << Port);
    		Pn_DIR &= ~(1<<PinNum);
    		Pn_PU |= 1<<PinNum;
    		break;
    	case 2:                                                                //推挽输出,高低电平强驱动
    		PORT_CFG &= ~(bP0_OC << Port);
    		Pn_DIR |= (1<<PinNum);
    		break;
    	case 3:                                                                //开漏输出,无上拉,支持输入
    		PORT_CFG |= (bP0_OC << Port);
    		Pn_DIR &= ~(1<<PinNum);
    		Pn_PU &= ~(1<<PinNum);
    		break;
    	case 4:                                                                //开漏输出,无上拉,当转变输出由低到高时,仅驱动2个时钟的高电平
    		PORT_CFG |= (bP0_OC << Port);
    		Pn_DIR |= 1<<PinNum;
    		Pn_PU &= ~(1<<PinNum);
    		break;
    	case 5:                                                                //弱准双向(标准51模式),开漏输出,带上拉
    		PORT_CFG |= (bP0_OC << Port);
    		Pn_DIR &= ~(1<<PinNum);
    		Pn_PU |= 1<<PinNum;
    		break;
    	case 6:                                                                //准双向(标准51模式),开漏输出,带上拉,当转变输出由低到高时,仅驱动2个时钟的高电平
    		PORT_CFG |= (bP0_OC << Port);
    		Pn_DIR |= 1<<PinNum;
    		Pn_PU |= 1<<PinNum;
    		break;
    	default:
    		break;
	}
	if(Port == 0){
		P0_DIR = Pn_DIR;
		P0_PU = Pn_PU;
	}
	if(Port == 1){
		P1_DIR = Pn_DIR;
		P1_PU = Pn_PU;
	}
	if(Port == 2){
		P2_DIR = Pn_DIR;
		P2_PU = Pn_PU;
	}
	if(Port == 3){
		P3_DIR = Pn_DIR;
		P3_PU = Pn_PU;
	}
  return 1;
}

/*******************************************************************************
* Function Name  : CH559P4Mode()
* Description    : CH559的P4端口初始化,P4默认是输入口
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void CH559P4Mode( )
{
	P4_DIR |= 0xff;                                                            //置1设置为输出
	P4_PU |= 0xff;                                                             //启动p4口内部上拉
	P4_CFG |= bP4_DRV;                                                         //该位为0则P4口驱动能力5mA,为1时为20mA
}

/*******************************************************************************
* Function Name  : CH559GPIOInterruptInit()
* Description    : CH559GPIO中断初始化,其他引脚如P5.5\P1.4\P0.3\P5.7\P4.1\RXD0设置同理
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void CH559GPIOInterruptInit()
{                                                      
	GPIO_IE &= ~bIE_IO_EDGE;                                                   //中断方式选择,该位为0则表示IO口电平中断,该位为1则表示IO口边沿中断
//	GPIO_IE |= bIE_RXD1_LO;                                                    //使能RXD1引脚的中断,其他引脚中断设置同理
  
	GPIO_IE |=bIE_P1_4_LO;//P14低电平触发
//	 GPIO_IE |=bIE_P5_5_HI;//电平模式高电平有效,边沿模式上升沿有效
//	GPIO_IE |=bIE_P0_3_LO;//P03 low level / falling edge低电平触发40
//	GPIO_IE |=bIE_P5_7_HI;//P57 high level / rising edge
//	GPIO_IE |=bIE_P4_1_LO;//P41 low level / falling edge一直触发
//	GPIO_IE |=bIE_RXD0_LO;//low level / falling edge P30
	
	
}

/*******************************************************************************
* Function Name  : GPIOInterrupt(void)
* Description    : GPIO 中断服务程序
* Input          : None
* Output         : None
* Return         : None   
*******************************************************************************/
void	GPIOInterrupt( void ) interrupt INT_NO_GPIO using 1                    //GPIO中断服务程序,使用寄存器组1
{  
    //RXD1_ = 1;
    printf("P5_IN %02X\n",(UINT16)P5_IN);                                     //bIO_INT_ACT为GPIO中断状态位
    //IE_GPIO = 0;   
	printf("hello world!");
	//使能GPIO中断、P2.6
}

void main( ) 
{
	 UINT16  value,value2;
//  CfgFsys( );  //CH559时钟选择配置   
    mDelaymS(5);           //等待内部晶振稳定
    P4_DIR = 0xff;//设置P4.x为输出口	
    
    mInitSTDIO( );         //串口0,可以用于调试
    printf("start ...\n");  
                                                                    
    XBUS_AUX |=  bALE_CLK_EN;   //关闭RS485模式 RS485_EN = 0;
    SER1_IER |= bIER_PIN_MOD1| bIER_PIN_MOD0;  //UART1 中断使能寄存器,脚位设置P2.6和P2.7,TNOW(P2.5)
//    RXD1_ = 1;//P40
		SCS =1;//P14上拉
    CH559GPIOInterruptInit();
    IE_GPIO = 1; //使能GPIO中断
    EA  = 1;    //使能全局中断 
	
		CH559GPIODrivCap(1,1);//IO驱动功率P1口,10ma
		CH559GPIODrivCap(2,1);//IO驱动功率P2口,20ma	

		value2=CH559GPIOModeSelt(1,2,2);//P1端口,推挽模式,P1.2
		value =CH559GPIOModeSelt(2,2,4);//P2端口,推挽模式,P2.4
//		CH559GPIOModeSelt(2,2,5);//P2端口,推挽模式,P2.5
	 


			led = 1;		
			led2= 1;
//			led3 = 0;	
	while(1){
		  led = ~led;		
			led2= ~led2;
//			led3 = ~led3;

		printf("P24_value=%d ,P12_value=%d \n",value,value2); 
		mDelaymS( 1000 );		
		}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值