在学习记录一当中说到本期回介绍相关芯片的中断设置,同样的也会了解到有关中断定时器或计数器初值的算法。这里只说定时器T0,T1。关于外部中断自己看学习记录(一)的pdf文件。
定时器T0,T1中断的简要说明
因为本人的一个习惯,不喜欢长篇大论。直接一步到位,不说其细节方面的内容了。想要自己了解的,自己搞懂怎么设置相关寄存器的看pdf文件。我这里直接给出对应定时器的寄存器设置方法。(图片解决,不在废话,请看下图)
从上面的图片可以看到对应的寄存器设置。当你仔细看完后,在看下面的代码就很容易理解了。
void TimeInit()
{
TMOD=0x05;//选16位向上计数
TCON0=0x00;//选128分频
TH0=0xff;//计算方式;2^n-(定时时间/(分频/时钟源))
TL0=0xce;//2^16-(200us/128/32MHz)=65536-(200us/4us)
ET0=1;//T0中断使能,可以理解为T0中断请求
TR0=1;//开定时器,可以理解为T0中断允许
}
利用T0中断实现1S闪烁
T0中断的初始化说完之后,就可以开始写其对应的中断要干的事情了(根具自己需求写,这里简单的运用一下);话不多说直接进入主题。
#include<SN8F5702.H>
/*
SN8F5702芯片只有P0.0-P0.7,P1.0-P1.7,P2.0-P2.1引脚
*/
sbit LED=P0^0;
#define uint unsigned int
#define uchar unsigned char
void GpioInit()
{
//用户在用C语言编写的时候,必须按照这个顺序编写设置系统时钟
CKCON = 0x70;
CLKSEL = 0x05;
CLKCMD = 0x69;
CKCON = 0x00;
//芯片IO口的设置,P0,P1,P2
//其中P1口有唤醒使能P1W
P0=0x01;//输出高低电平控制,POM相应位使能
P0M=0x01;//定义输入0输出1。
P0UR=0x00;//内置上拉电阻控制,禁止0使能1
P1=0x00;
P1M=0x00;
P1UR=0x00;
P1W=0x00;//唤醒禁用0,使能1
P2=0x00;
P2M=0x00;
P2UR=0x00;
}
void TimeInit()
{
TMOD=0x05;//选16位向上计数
TCON0=0x00;//选128分频
TH0=0xff;//计算方式;2^n-(定时时间/(分频/时钟源))
TL0=0x06;//2^16-(1ms/128/32MHz)=65536-(1ms/4us)=65286(ff06)
ET0=1;//T0中断使能
TR0=1;//开定时器
}
void main()
{
GpioInit();
TimeInit();
EAL=1;//总中断控制
while(1);
}
void Timer0_ISR(void) interrupt ISRTimer0
{
static uint i=0;
TH0=0xff;
TL0=0x06;
i++;
if(i>=1000)
{
i=0;
LED=~LED;
}
}
可能很多人看着也就那样,但如果你自己去看芯片的手册,自己去理解,就知道其中的艰辛。当然本次重点就在与初值的计算,跟89C51单片机不同,本人也是废了很长时间才验证得到,其他如有类似芯片可提供参考。
利用T0定时器实现次数闪灭
同样原理,自己稍微思考就可以得到。这里只提供一个中断参考,有其他想法的自己去编写验证。
void Timer0_ISR(void) interrupt ISRTimer0
{
static uint i=0,count=0;
TH0=0xff;
TL0=0x06;
i++;
if(i>=500)
{
i=0;
LED=~LED;
count++;//LED灯得闪烁,亮5次灭。
if(count>=10)
{
TR0=0;
LED=0;
}
}
}
利用T0定时器实现呼吸灯效果
网上关于呼吸灯的介绍一大堆,各有各的代码,各有各的实现方式,本人这里也借用了网上的呼吸灯代码来实现。认为这段代码是比较好理解的。在验证的过程中,实现的效果不是太好,具体原因还未查明。最合适的设置定时为200us,计数100。这个可能与分频和芯片时钟有关。
#include<SN8F5702.H>
/*
SN8F5702芯片只有P0.0-P0.7,P1.0-P1.7,P2.0-P2.1引脚
*/
sbit LED=P0^0;
#define uint unsigned int
#define uchar unsigned char
uint i,k;
void GpioInit()
{
//用户在用C语言编写的时候,必须按照这个顺序编写设置系统时钟
CKCON = 0x70;
CLKSEL = 0x05;
CLKCMD = 0x69;
CKCON = 0x00;
//芯片IO口的设置,P0,P1,P2
//其中P1口有唤醒使能P1W
P0=0x01;//输出高低电平控制,POM相应位使能
P0M=0x01;//定义输入0输出1。
P0UR=0x00;//内置上拉电阻控制,禁止0使能1,IO口为输出模式是建议禁止
P1=0x00;
P1M=0x00;
P1UR=0x00;
P1W=0x00;//唤醒禁用0,使能1
P2=0x00;
P2M=0x00;
P2UR=0x00;
}
void TimeInit()
{
TMOD=0x05;//选16位向上计数
TCON0=0x00;//选128分频
TH0=0xff;//计算方式;2^n-(定时时间/(分频/时钟源))
TL0=0xce;//2^16-(400us/128/32MHz)=65536-(400us/4us)=65436(ff9e)
ET0=1;//T0中断使能
TR0=1;//开定时器
}
uint Tcount=0, dutyfactor=0, direct=0;
void ledbreath()
{
if(Tcount >= 100)
{
Tcount=0;
if(direct==0)
{
dutyfactor++;
}
else if(direct == 1)
{
dutyfactor--;
}
}
else Tcount++;
if(dutyfactor <= 0)
{
direct=0;
}
else if(dutyfactor >= 100)
{
direct=1;
}
if(Tcount < dutyfactor)
{
LED=0;
}
else
{
LED=1;
}
}
void main()
{
GpioInit();
TimeInit();
EAL=1;//总中断控制
LED=0;
while(1);
}
void Timer0_ISR(void) interrupt ISRTimer0
{
TH0=0xff;
TL0=0xce;
ledbreath();
}
或者这个也还不错,不过没有用定时器
#include<SN8F5702.H>
/*
SN8F5702芯片只有P0.0-P0.7,P1.0-P1.7,P2.0-P2.1引脚
*/
#define uint unsigned int
#define uchar unsigned char
#define ulong unsigned long
sbit LEDR=P0^5;
#define PWM_CYCLE 255//周期
uint a,k;
void delay(uchar j)
{
for(a=j;a>0;a--)
for(k=0;k<20;k++);
}
void GpioInit()
{
//用户在用C语言编写的时候,必须按照这个顺序编写设置系统时钟
CKCON = 0x70;
CLKSEL = 0x05;
CLKCMD = 0x69;
CKCON = 0x00;
//芯片IO口的设置,P0,P1,P2
//其中P1口有唤醒使能P1W
P0=0x20;//输出高低电平控制,POM相应位使能
P0M=0x20;//定义输入0输出1。
P0UR=0x00;//内置上拉电阻控制,禁止0使能1,IO口为输出模式是建议禁止
P1=0x00;
P1M=0x00;
P1UR=0x00;
P1W=0x00;//唤醒禁用0,使能1
P2=0x00;
P2M=0x00;
P2UR=0x00;
}
void pwmduty(uint duty)
{
LEDR=1;
delay(duty);
LEDR=0;
delay(PWM_CYCLE-duty);
}
uint duty_cycle=0;
void main()
{
GpioInit();
//LEDR=0,LEDG=0,LEDB=0;
while(1)
{
WDTR = 0x5A;
for(duty_cycle=0;duty_cycle<PWM_CYCLE;duty_cycle++)
{
pwmduty(duty_cycle);
}
for(duty_cycle=PWM_CYCLE;duty_cycle>0;duty_cycle--)
{
pwmduty(duty_cycle);
}
}
}
下次介绍ADC得采样与相关计算