写在前面
这段时间接触九齐的051D,记录一下怎么快速入门这款单片机
定时器
跟普通的8051单片机使用方法类似,直接上代码:
#include <ny8.h>
#include "ny8_constant.h"
#define UPDATE_REG(x) __asm__("MOVR _" #x ",F")
#define u16 unsigned int
#define u8 unsigned char
void delay_ms(int);
#define key PORTBbits.PB0
#define led1 PORTBbits.PB1
#define led2 PORTBbits.PB3
unsigned char key_state=0;
void delay_us(int count) //@16M 2T 2.5us
{
for(;count>0;count--);
}
void delay_ms(int count) //@8m 4T 1ms
{
int i;for(;count>0;count--){for(i=0;i<=100;i++);}
}
void sys_init(void)
{
PCON &= ~(1<<3); //关闭LVR 需要在IC_CONFIG里面设置寄存器配置
}
void io_init(void)
{
IOSTB|=(1<<0); //PB0输入
IOSTB|=(1<<2); //PB2输入
IOSTB&=~(1<<1); //PB1输出
IOSTB&=~(1<<3); //PB3输出
BPHCON=0; //开启B0口上拉电阻
INTE|=(1<<1); //开启B口电平中断
PORTB=0XFF;
led1=1; led2=1; key=1;
}
//==T0时间计算================================================
// 时间 T 2T模式 2分频 计数空间
// 1/16M * 2 * 2 255-TMR0 +2
// 50us = 1/16M * 2 * 2 200
//1M 1.76MS
void time0_init(void)
{
T0MD &=~((1<<5)|(1<<3)|(1<<2)|(1<<1)|(1<<0)); //FINST预分频给T0且为2分频
TMR0 = 50;
INTE |= (1<<0); //开启T0中断
PCON1 |= (1<<0); //开启T0
}
void time1_init(void);
void main(void)
{
io_init();
delay_ms(80);
INTF = 0; //清除所有中断标志
DISI(); //关闭总中断
ENI(); //开启总中断
while(1)
{
if(key==1)
{
if(key_state == 1)
{
led1 = ~led1;
led2 = ~led2;
key_state = 0;
}
SLEEP();
}
}
}
//! interrupt service routine
void isr(void) __interrupt(0)
{
if(INTFbits.INTIF) //INT中断
{
INTFbits.INTIF=0;
}
if(INTFbits.PBIF) //PB中断
{
INTFbits.PBIF=0;//清除外中断标志
if(key==0) //按下标记
{
delay_ms(30);
if(key==0) //按下标记
{
key_state = 1;
}
}
}
if(INTFbits.T0IF) //定时器0中断 //1M 1.76MS
{
INTFbits.T0IF=0;
TMR0 = 50;
}
}
这段代码比较简单,只用到了PB电平变化中断,如果要用定时器中断只需要在主函数里添加响应的init函数就行了。关于溢出时间,这条公式不是非常准,我在九齐的官网实例代码里没有看到对应的公式,只能结合逻辑分析仪一点点手动调,而且由于没有自动重装功能,定时器有一定的误差,如果需要做时间计算,需要做时间补偿。
所有的MCU设置在这里:
比如我要产生一个50us的中断,首先选择MCU的内部震荡频率是8Mhz,然后选择4T模式,最后再在定时器设置的时候,把内部时钟分配给定时器,不然的话MCU会分配给看门狗计时,然后设置成2分频,这样MCU一次计时就是1us,定时50us就只需要计时50次。这个初值不一定准,结合示波器或者逻辑分析仪慢慢去调才能减小误差。
另外,051D,053D,062D中文手册需要的可以私信,看到了会回。
云盘:https://pan.baidu.com/s/1v_hHeEACYy8HLKO9hrA0wA
提取码:r7aq