|
本帖最后由 damiaa 于 2017-10-16 09:28 编辑
CH554评测】第三篇 测试一下定时器
定时器,是单片机的必需品,无任定时,还是做PWM,还是测量时间间隔等都要用到.
CH554有两个16位定时器,Timer0/1。Timer2.下面只讨论定时器0和1.
相关寄存器:
TH1 8Dh Timer1 计数高字节 xxh
TH0 8Ch Timer0 计数高字节 xxh
TL1 8Bh Timer1 计数低字节 xxh
TL0 8Ah Timer0 计数低字节 xxh
TMOD 89h Timer0/1 方式寄存器 00h
TCON 88h Timer0/1 控制寄存器 00h
每个定时器有三个寄存器,一个是计数的,一个是模式设置的,还一个是控制的。这就是基本三元素。
定时/计数器 0/1 控制寄存器(TCON):
位 名称 访问 描述
7 TF1 RW Timer1 溢出中断标志位,进入定时器 1 中断后自动清零
6 TR1 RW Timer1 启动/停止位,置 1 启动,由软件置位或者清零
5 TF0 RW Timer0 溢出中断标志位,进入定时器 0 中断后自动清零
4 TR0 RW Timer0 启动/停止位,置 1 启动,由软件置位或者清零
3 IE1 RW INT1 外部中断 1 的中断请求标志位,进入中断后自动清零
2 IT1 RW INT1 外部中断 1 触发方式控制位,该位为 0 选择外部中断为低电平触发;该位为 1 选择外部中断为下降边沿触发
1 IE0 RW INT0 外部中断 0 的中断请求标志位,进入中断后自动清零
0 IT0 RW INT0 外部中断 0 触发方式控制位,该位为 0 选择外部中断为低电平触发;该位为 1 选择外部中断为下降边沿触发
这里TCON只有4位给了定时器,其他的给外部中断用的,
定时/计数器 0/1 方式寄存器(TMOD):
位 名称 访问 描述
7 bT1_GATE RW 门控使能位,控制 Timer1 启动是否受外部中断信号 INT1 的影响。该位为 0 则定时/计数器 1 是否启动与 INT1 无关;该位为 1
则只有 INT1 引脚为高电平并且 TR1 为 1 时才能启动
6 bT1_CT RW 定时或者计数方式选择位,该位为 0 工作于定时方式;该位为 1工作于计数方式,使用 T1 引脚的下降沿作为时钟
5 bT1_M1 RW 定时/计数器 1 模式选择高位
4 bT1_M0 RW 定时/计数器 1 模式选择低位
3 bT0_GATE RW门控使能位,控制 Timer0 启动是否受外部中断信号 INT0 的影响。该位为 0 则定时/计数器 0 是否启动与 INT0 无关;该位为 1
则只有 INT0 引脚为高电平并且 TR0 为 1 时才能启动
2 bT0_CT RW 定时或者计数方式选择位,该位为 0 工作于定时方式;该位为 1工作于计数方式,使用 T0 引脚的下降沿作为时钟
1 bT0_M1 RW 定时/计数器 0 模式选择高位
0 bT0_M0 RW 定时/计数器 0 模式选择低位
bTn_M1 ,bTn_M0
0 0 模式 0:13 位定时/计数器 n,计数单元由 TLn 的低 5 位和 THn 组成,TLn 的高 3 位无效。计数从 13 位全为 1 变成全为 0 时,设置溢出标志 TFn,并需重置初值
0 1 模式 1:16 位定时/计数器 n,计数单元由 TLn 和 THn 组成。计数从 16 位全为 1变成全为 0 时,设置溢出标志 TFn,并需重置初值
1 0 模式 2:8 位重载定时/计数器 n,计数单元使用 TLn,THn 作为重载计数单元。计数从 8 位全为 1 变成全为 0 时,设置溢出标志 TFn,并自动从 THn 加载初值
1 1 模式 3:如果是定时/计数器 0,那么定时/计数器 0 被分成 2 个部分 TL0 和 TH0,TL0 作为 8 位定时/计数器使用,占用 Timer0 的全部控制位;而 TH0 也做另一个
8 位定时器使用,占用 Timer1 的 TR1、TF1 和中断资源,并且此时 Timer1 仍然可用,只是不能使用启动控制位 TR1 和溢出标志位 TF1。如果是定时/计数器 1,那
么进入模式 3 将停止定时/计数器 1。
关于程序
D:\touch\ch554\CH554EVT\EVT\EXAM\Timer目录里有个例子,跑跑?main.c中调用以下几个在Timer.c中定义的函数初始化和期待定时器(我们这里用定时器1)
#ifdef T1_INT
printf("T1 Test ...\n");
mTimer1Clk12DivFsys(); //T1定时器时钟设置
mTimer_x_ModInit(1,2); //T1 定时器模式设置
mTimer_x_SetData(1,0x6464); //T1定时器赋值 这里用100 系统时钟为12M,12分频后刚好1US,这样定时器就是100US,加上定时器里面1万次闪动一下。刚好1秒。
mTimer1RunCTL(1); //T1定时器启动
ET1 = 1; //T1定时器中断开启
EA = 1;
while(1);
#endif
顺便说一下:这个例子中系统时钟是12M,CfgFsys( ); 这个函数确定的,如果要更改,到里面去改,就是CLOCK_CFG的低三位配置系统时钟 前面要先写SAFE_MOD = 0x55;SAFE_MOD = 0xAA;
具体看系统时钟配置方面的资料和代码。
Timer.c中有中断响应函数,这里用P1.6,P1.7 LED指示,因为定时时间太短,肉眼无法分辨,就用个静态变量,让每10000次闪一下,刚好凑够1秒。这样就可以看到效果了。
#ifdef T1_INT
/*******************************************************************************
* Function Name : mTimer1Interrupt()
* Description : CH554定时计数器0定时计数器中断处理函数
*******************************************************************************/
void mTimer1Interrupt( void ) interrupt INT_NO_TMR1 using 2 //timer1中断服务程序,使用寄存器组2
{ //方式3时,Timer1停止
static UINT16 timbuf=0;
timbuf++;
if(timbuf >10000)
{
timbuf=0;
RXD1 = ~RXD1;
TXD1 = ~TXD1;//SCK = ~SCK;
}
}
#endif
下面附上HEX文件:
CH554DEMO_MODI.hex
(5.96 KB, 下载次数: 2)
今天用这个为自己做了个定时器,可以定时N个时间,但苦于电路的原因,没有蜂鸣器提示,只好先 用个LED提示,目前没用到小时,也只定时8个时间。
Timer.h中
typedef struct CCLOCK
{
UINT8 hour;
UINT8 min;
UINT8 second;
UINT8 secondflag;//为了主程序中每秒只判断一次,避免一秒中重复判断
}CLOCK;
Timer.c中
CLOCK thisclock;
CLOCK *pclock =&thisclock;
void clockinc(CLOCK *pclock)
{
pclock->second++;
pclock->secondflag++;
if(pclock->second>=60)
{
pclock->second=0;
pclock->min++;
if(pclock->min>=60)
{
pclock->min =0;
pclock->hour++;
if(pclock->hour >=24) pclock->hour =0;
}
}
}
void mTimer1Interrupt( void ) interrupt INT_NO_TMR1 using 2
{
static UINT16 timbuf=0;
timbuf++;
if(timbuf >10000)
{
timbuf=0;
clockinc(pclock);
}
}
main.c中
extern CLOCK thisclock;
UINT8 timdata[16] = {2,30, 6,50, 11,10, 15,30, 19,50, 24,10, 28,30, 32,50};//37,10 //如果要用到小时,这里增加小时,比较的时候也增加
//UINT8 timdata[24] = {0,2,30, 0,6,50, 0,11,10, 0,15,30, 0,19,50, 0,24,10, 0,28,30, 0,32,50};//37,10
while(1)
{
if(thisclock.secondflag)
{
thisclock.secondflag =0;
if(status <8)
{
if((thisclock.min == timdata[status*2])&&(thisclock.second==timdata[status*2+1]))
// if((thisclock.hour == timdata[status*3])&&(thisclock.min == timdata[status*3+1])&&(thisclock.second==timdata[status*3+2]))//如果要用定时器
{
RXD1 = 0;//定时时间到闪动一下
status++;
}
else
RXD1 = 1;
}
}
}
程序代码:
Timer.zip
(164.63 KB, 下载次数: 11)
后续有机会看是否 改为USB能配置定时。
此内容由EEWORLD论坛网友damiaa原创,如需转载或用于商业用途需征得作者同意并注明出处
|
|