logo

CH563评估板测试2——外部中断

  春节前做了一个简单的开箱测试,跑了个流水灯,大概了解了一下CH563的基本开发流程。假期间天天走亲访友、吃喝醉睡,板子扔在一边整个假期居然一下也没碰。昨天上班,刚开工,没什么事干,又把板子拿起来测试了一下CH563的中断系统。

  CH563的中断模式与其它ARM芯片差不多,分为IRQ与FIQ,同时每种模式还分为查询入口与直跳入口中断。第一篇测试文章里提到的IRQ_Handler(),FIQ_Handler()这两个函数就是默认的查询入口中断处理函数。在使用查询入口中断时,我们要把中断处理相关内容写到这两个函数里。由于在查询方式下所有的中断源发生中断后都是跳向这两个函数,所以一般要在这两个函数里先对中断源进行判断,再跳转到相应的处理程序里。显然这种方式会多消耗一些处理器时间。

  而相对的直跳入口与51单片机的中断处理差不多,都是通过指定中断向量,一旦某一特定中断发生时,就直接跳转到指定的中断处理函数里去,从而节省了一点处理器时间。

  为了了解CH563的中断处理方式,俺设计了两个小程序来分别测试查询入口与直跳入口。使用的都是PB管脚做为外中断源,利用板上的三个LED灯来指示是否进入了中断处理程序。

  程序1为查询入口,中断源为PB6、PB7。PB6设定为上升沿触发,PB7设定为下降沿触发。PB7是直接利用板上的按钮S2来触发中断,从而控制三个LED依次单独点亮。PB6则用了一根杜邦线通过与GND的接触来触发中断,将三个LED的状态反转。

下面为程序1的代码,具体寄存器的作用都作了注释:

#include "CH563BAS.H"
#include "CH563SFR.H"
#include "SYSFREQ.H"

#define LED 0x38

CHAR LEDMASK[]={0x30,0x28,0x18};
CHAR IntTime;


__irq void IRQ_Handler()
{
	  if(R8_INT_STATUS_PB_0&0x80)			//是否为PB.7中断
		{
		Delay_ms(30);           //在中断处理程序里做延时消抖,就是这么任性:)
		if(!(R8_PB_PIN_0&0x80))					
		{
			if(IntTime<3)
			{
				R8_PB_CLR_0 |=LED; //LED清零
				R8_PB_OUT_0 |= LEDMASK[IntTime];
			}
			if(++IntTime>=3) IntTime=0;
		}
		}
		if(R8_INT_STATUS_PB_0&0x40)	//是否为PB.6中断
		{
			Delay_ms(30);
			if((R8_PB_PIN_0&0x40))
			{
			R8_PB_OUT_0 ^=LED; 						          	}
		}
    R8_INT_STATUS_PB_0 = 0xff;         // 中断标志清零 
    
}
	
__irq void FIQ_Handler(){}
	
void IRQ_InitPB_7_6(void)
{
	R8_PB_PU_0 |= 0xc0;	//设置PB.7.6为上拉
	R8_PB_DIR_0 &= ~0xc0;	//设置PB.7.6为输入

	R8_INT_ENABLE_PB_0 |= 0xc0;	//打开两IO外部中断
	R8_INT_MODE_PB_0 |=0xc0;	//设置中断触发方式为边沿触发
	R8_INT_POLAR_PB_0 &= 0x7f;	//设置PB.7下降沿触发
	R8_INT_POLAR_PB_0 |= 0x40;	//设置PB.6上升沿触发
	R8_INT_STATUS_PB_0 = 0xff;
	
	R8_INT_EN_IRQ_1 |= RB_IE_IRQ_PB;	//使能PB口IRQ中断
	R8_INT_EN_IRQ_GLOB|= RB_IE_IRQ_GLOB;   //使能全局IRQ中断
}

void Init_LED(void)
{
	
	R8_PB_DIR_0 |= LED;		//PB.3.4.5为输出
	R8_PB_OUT_0 |=	LED;																						
}
	

int main()
{
	IRQ_InitPB_7_6( );
	Init_LED();
	IntTime=0;
	while(1)
	{
		
	}
}





接一楼,下面为直跳入口中断处理的例子代码,其实与查询入口区别不大,主要是要指定相应的中断向量,具体的寄存器设置见下面的代码。

    为了与查询入口的程序功能相区别,下面的程序里将中断源设置为PB0,1,2,7四个管脚。PB7的功能与之前一样,只是换了种写法。PB0,1,2则分别控制一个LED,相互之间互不影响。代码里同样做了比较详细的注释供大家参考:

#include "ch563sfr.h"
#include "sysfreq.h"

#define LED 1
CHAR led_bit;

__irq void IRQ_Handler(void)
{
	
}


__irq void FIQ_Handler(void)
{
	
}



__irq extern void  PB_Handler(void)   //直跳中断处理函数
{
	if(R8_INT_STATUS_PB_0&0x80)
	{
		Delay_ms(30);
		if(!(R8_PB_PIN_0&0x80))
		{
			if(led_bit<3) led_bit=5;
			R8_PB_OUT_0 =~(LED<<led_bit);
			led_bit--;
		}
	}
	
	if(R8_INT_STATUS_PB_0&0x01)
	{
		Delay_ms(30);
		if(!(R8_PB_PIN_0&0x01))
		{
			R8_PB_OUT_0 ^=  0x20;
		}
		
	}
	
	if(R8_INT_STATUS_PB_0&0x02)
	{
		Delay_ms(30);
		if(!(R8_PB_PIN_0&0x02))
		{
				R8_PB_OUT_0 ^= 0x10;
		}
		
	}
	
	if(R8_INT_STATUS_PB_0&0x04)
	{
		Delay_ms(30);
		if(!(R8_PB_PIN_0&0x04))
		{
				R8_PB_OUT_0 ^= 0x08;
		}
		
	}
	
	R8_INT_STATUS_PB_0 =0xff;
}

void PB_INT_Init(void)			//中断初始化函数,将PB.0.1.2.7做为中断源
{
	R8_PB_PU_0|=0x87;								
	R8_PB_DIR_0 &=~0x87;
		
	R8_INT_ENABLE_PB_0 |= 0x87;
	R8_INT_MODE_PB_0 |= 0x87;
	R8_INT_POLAR_PB_0 &= ~0x87;
	
	R8_SAFE_ACCESS_SIG = 0x57 ;  // 要实现直跳中断入口必须执行此步骤进入安全模式
        R8_SAFE_ACCESS_SIG = 0xA8 ;
	R32_INT_VEC_PB = MAKE_INT_VEC_IRQ( PB_Handler );//设置PB端口直跳中断向量寄存器
	R8_INT_VEC_IRQ |=RB_IV_IRQ_PB;  //使能PB中断直跳入口
	R8_SAFE_ACCESS_SIG = 0x00 ;
	
	R8_INT_STATUS_PB_0 =0xff;
	
	R8_INT_EN_IRQ_1 |= RB_IE_IRQ_PB;
	R8_INT_EN_IRQ_GLOB |= RB_IE_IRQ_GLOB;
	
	
}

void LED_IO_Init()
{
	
	R8_PB_DIR_0 |= 0x38;
	R8_PB_OUT_0 |= 0x38;
}

int main()
{
	PB_INT_Init();
	LED_IO_Init();
	led_bit=5;
	
	while(1)
	{
	}
	
	
}

经过这两种程序的编写与实际测试,对CH563的中断处理有了一个基础的认识与了解。这篇测试就写到这了,后面我会将定时器中断的测试进行整理,并发贴。


官方的例程是有点小问题吧


                                         

官方的例程是有点小问题吧

                                 

官方没有给外部中断直跳入口的例程,ds里给了一点文字说明。中断还算好的,其他的模块说明更不好明白。我卡在pwm上了,能进中断,但相应的管脚就是没输出。



有技术疑问可联系张工:025-52638371


PWM操作流程:

1、配置对应引脚方向为输出

2、配置PWM周期和占空比

3、配置对应定时器的“模式控制寄存器”(R8_TMRx_CTRL_MOD位2和位3置1)

如果需要使用中断,则配置对应中断即可。详见EVT例子程序。

 

Mail: zfl@wch.cn Web: http://wch.cn Tel: +86-025-52638370 Fax: +86-025-84730778

我就是这样写的,但PWM相应的引脚测不到脉冲。是每次输出都要配置一遍周期与占空比吗?


                                         

PWM操作流程:

1、配置对应引脚方向为输出

2、配置PWM周期和占空比

3、配置对应定时器的“模式控制寄存器”(R8_TMRx_CTRL_MOD位2和位3置1)

如果需要使用中断,则配置对应中断即可。详见EVT例子程序。

 

                                 

下面是我按手册里对PWM的说明写的一个简单的测试程序,但我始终无法在PWM2上得到脉冲,通过在IRQ函数里添加调试标志,发现RB_TMR_IE_DATA_ACT中断始终没有发生。我不知问题出在什么地方,请ZFL指导一下,谢谢。

#include "CH563SFR.H"
#include "sysfreq.h"

__irq void IRQ_Handler()
{
	
	if(R8_INT_FLAG_0&RB_IF_TMR0)
	{
		UINT8 i;
		i=R8_TMR0_INT_FLAG;
		if(i&RB_TMR_IF_DATA_ACT)
		{
		     R8_TMR0_INT_FLAG |= RB_TMR_IF_DATA_ACT;                                                  R8_INT_FLAG_0 |= RB_IF_TMR0; 
		}
		
		if(i&RB_TMR_IF_CYC_END)
	        {			
                    R8_TMR0_INT_FLAG|=RB_TMR_IF_CYC_END;  
                    R8_INT_FLAG_0 |= RB_IF_TMR0;   
                }
	}
		
	
}

__irq void FIQ_Handler()
{
	
}

void PWM_Init()
{
	R8_PB_DIR_0|=PWM2;
	R32_TMR0_FIFO=100000000/2;
	R32_TMR0_CNT_END=100000000;
	R8_TMR0_CTRL_MOD&=~(RB_TMR_MODE_NRZI|RB_TMR_ALL_CLEAR|RB_TMR_MODE_IN);
	R8_TMR0_CTRL_MOD|=(RB_TMR_OUT_EN|RB_TMR_COUNT_EN)
	;
	R8_TMR0_INTER_EN |=(RB_TMR_IE_CYC_END|RB_TMR_IE_DATA_ACT);
	
	R8_INT_EN_IRQ_0|=RB_IE_IRQ_TMR0;
	R8_INT_EN_IRQ_GLOB|=RB_IE_IRQ_GLOB;
}

int main()
{
	PWM_Init();
	
	while(1)
	{}
}



只有登录才能回复,可以选择微信和github账号登录