|

楼主 |
发表于 2025-3-23 21:11:16
|
显示全部楼层
开源...
欢迎大家讨论交流。
/*激光转速测量*/
/*设定内部晶振24M 时钟周期0.041666us 1T机器周期0.041666us
使用stc8g1k08a,pcb文件名leise6.lay6,红点光笔拆激光管,工作电压3v,激光调制接收管180k-200kHz(入光1,遮光0) */
#include "intrins.h"
#include "stc8g.h"
#include "codetab.h"
#include "iic.h"
#include "oled12832.h"
#include "NECir.h"
//#include "BA5104ir.h"
//sbit p54=P5^4; //iic-scl
//sbit p55=P5^5; //iic-sda
sbit ir=P3^2; //int0
sbit p33=P3^3;
sbit key=P3^0;
unsigned char mun;
unsigned int tes,ird0,ird1;
unsigned char irdat,kx,ok5104;
//在单片机中,CCP是英文单词Capture(捕获),Compare(比较),PWM(脉宽调制)的缩写。
//这个模块可配置为工作在输入捕捉、定时器比较或 PWM 输出方式下。
//可工作在捕捉输入、比较输出和脉宽调制输出三种状态,三种状态各自独立工作。
//PCA 计数器
//激光发射调制180-200kHz
void stcIO_Init(void)
{
P3M0=0x00; //设置P3.0-P3.7为双向口模式
P3M1=0x00;
P5M0=0x00; //设置P5.0-P5.7为双向口模式
P5M1=0x00;
P0M0 = 0x00;
P0M1 = 0x00;
P1M0 = 0x00;
P1M1 = 0x00;
P2M0 = 0x00;
P2M1 = 0x00;
// P3M0 = 0x00;
// P3M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
// P5M0 = 0x00;
// P5M1 = 0x00;
P3=0xff; //芯片内部没有打线到外部管脚的IO是悬空的,设置成准双向模式,并固定输出高电平
P5=0xff;
}
//调制190k 2.63us高/2.63us低
//*************定时器0初始化*********************//
void laser_Timer0_Init(void) //2.625微秒@24.000MHz 190kHz laser
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式 16位自动重装
TL0 = 0xc1; //设置定时初始值
TH0 = 0xFF; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器中断
}
void ir_Timer0_Init(void) //32毫秒@24.000MHz 定时器0/12T模式/16位不自动重载/最大32毫秒溢出
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式 16位不自动重载
TL0 = 0x00; //设置定时初始值
TH0 = 0x00; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 0; //关闭定时器0中断
}
/************************************************
BA5104的编码格式:
每一帧遥控码的长度为12位,高位在前,包括3位起始码位(110)、2位用户码位、7位指令码位。
每一帧遥控码的时间间隔为4T(6.7516ms),其中T=1.6879ms为每一位遥控码的周期。
遥控码“0”用1/4T的高电平(0.395ms)、3/4T(1.284ms)的低电平表示,遥控码“1”用3/4T的高电平、1/4T的低电平表示。
关-0x01 摇头-0x10 定时-0x08 风类-0x04 开/风速-0x02 彩灯-0x43
110 11 1000011=0x0dc3=67 彩灯
*************************************************/
void do_ir5104()
{
//uchar k;
if(ird0<<4==ird1<<4)
{
show[7]=(ird0>>9&0x07)>>4; //0x00
show[6]=(ird0>>9&0x07)&0x0f; //0x06
show[3]=(ird0>>7&0x03)>>4;
show[2]=(ird0>>7&0x03)&0x0f;
show[1]=(ird0&0x7f)>>4;
show[0]=(ird0&0x7f)&0x0f;
//_nop_();
//_nop_();
OLED_WrCmd(0x81);//--set contrast control register 设置对比度 0x00-0xff 值增加对比度增加
OLED_WrCmd(0xff);//0xff);
t1k=0;
}
else
{
ird1=ird0;
}
irdat=kx=ok5104=0;
TR0=0;
ET0=0;
}
void TM0_Isr() interrupt 1
{
switch (mun)
{
case 0:
p33 = !p33;
break;
case 2:
TR0=0;
ird0=(ird0<<1)|ir;
irdat++;
if(irdat>11)
{
ok5104=1;
}
break;
default:
break;
}
}
/**********************以下转速测量************************/
//1w转 每转脉冲间隔6000us
//200转 每转脉冲间隔300000us=300ms
//24M晶振 定时器12T模式 机器周期0.5us 最小可测每分钟10转 最大可测每分钟100万转 显示只有5位数最高10万转
void Timer1_Init(void) //25毫秒@24.000MHz 16位不自动重装 机器周期0.5us
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x10; //设置定时器模式
TL1 = 0xB0; //设置定时初始值
TH1 = 0x3C; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1; //使能定时器中断
}
unsigned int t1k;
unsigned long speedT;
void TM1_Isr() interrupt 3 //定时器1中断
{
TL1 = 0xB0; //设置定时初始值
TH1 = 0x3C; //设置定时初始值
//TR1 = 1; //定时器1开始计时
t1k++;
}
void int0_Init(void)
{
IT0=0; //IT0 = 1; //使能INT0下降沿中断
EX0 = 1; //使能INT0中断
//EA = 1;
}
void INT0_Isr() interrupt 0 //ir接收中断0
{
if(ir)
{
switch (mun)
{
case 0: //转速
speedT=((TH1-0x3c)*256+(TL1-0xb0))/2+(t1k*25000UL); //us "UL"指定"25000"为unsigned long,否证keil会导致溢出
TL1 = 0xB0; //设置定时初始值
TH1 = 0x3C; //设置定时初始值
//TR1 = 1; //定时器1开始计时
t1k=0;
//ET1 = 1; //使能定时器中断
break;
case 1: //NEC解码
Tc=TH0*256+TL0; //提取中断时间间隔时长
TH0=0;
TL0=0; //定时中断重新置零
if((Tc>Imin)&&(Tc<Imax))
{
m=0;
f=1;
return;
} //找到启始码
if(f==1)
{
if(Tc>Inum1&&Tc<Inum3)
{
Im[m/8]=Im[m/8]>>1;
m++; //取码//Im[m/8]=Im[m/8]>>1|0x80; m++;
}
if(Tc>Inum2&&Tc<Inum1)
{
Im[m/8]=Im[m/8]>>1|0x80;
m++;//Im[m/8]=Im[m/8]>>1; m++; //取码
}
if(m==32)
{
m=0;
f=0;
if(Im[2]==~Im[3])
{
IrOK=1;
}
else
{
IrOK=0; //取码完成后判断读码是否正确
}
}
//准备读下一码
}
break;
case 2: //BA5104解码
if(!kx)
{
tes=TH0*256+TL0; //提取中断时间间隔时长
TH0=0;
TL0=0;
ET0=0;
TR0=1; //定时中断重新置零
if((tes>16492)&&(tes<17794))//11.0592_if((tes>7600)&&(tes<8200)) //8246us-8897us
{
//24M _if((tes>16492)&&(tes<17794)) //8246us-8897us
kx=1;
}
}
if(!ok5104&&kx) //11.0592_ TH0=0xfc;TL0=0xf1;
{
TL0=0x68; //溢出时间844us,取遥控码“0”或“1”的一个T的一半(0.84395ms),根据此时的高低电平判断是0还是1//
TH0=0xf9;
TR0=1;
ET0=1;
}
break;
default:
break;
}
}
}
unsigned dis[5]= {0x0a,0x0a,0x0a,0x0a,0x0a};
unsigned dis_tmp[5]= {0,0,0,0,0};
unsigned irdis[8]= {1,1,1,1,1,1,1,1};
unsigned long rpm;
void do_rpm (void)
{
rpm=60000000/speedT;//t1k;//60000/speedT;
if(!speedT)
{
rpm=0;
}
//rpm=mun;
dis_tmp[4]=rpm%100000/10000;
dis_tmp[3]=rpm%10000/1000;
dis_tmp[2]=rpm%1000/100;
dis_tmp[1]=rpm%100/10;
dis_tmp[0]=rpm%10;
}
void scan_key(void)
{
static unsigned int k;
if(t1k==600)
{
if(mun==0)
{
TR0=0;
p33=0;
}
}
if(t1k==800)
{
OLED_WrCmd(0x81); //--set contrast control register 设置对比度 0x00-0xff 值增加对比度增加
OLED_WrCmd(0x00);//0xff);
}
if(!key)
{
OLED_WrCmd(0x81); //--set contrast control register 设置对比度 0x00-0xff 值增加对比度增加
OLED_WrCmd(0xff);//0xff);
TR0=1;
t1k=0;
k++;
if(k==1500) //开关长按约3秒,改变状态
{
mun++;
if(mun>2)
{
mun=0;
}
OLED_CLS();
dis[0]=dis[1]=dis[2]=dis[3]=dis[4]=0x0b;
irdis[7]=irdis[6]=irdis[5]=irdis[4]=irdis[3]=irdis[2]=irdis[1]=irdis[0]=0x10;
switch (mun)
{
case 0: //测转速
laser_Timer0_Init();
break;
case 1: //红外NRC格式解码
ir_Timer0_Init();
p33=0;
OLED_P8x16Str(30,0,"NEC KEY:");
break;
case 2: //红外BA5104格式解码
ir_Timer0_Init();
p33=0;
OLED_P8x16Str(30,0,"5104 KEY:");
break;
default:
break;
}
}
}
else
{
k=0;
}
if((mun==1)&&IrOK)
{
irshow();
}
}
//**********************将P0.5,P0.7,P3.6,和P3.7片内上拉电阻使能************************//
// P_SW2 |= 0X80; //将EAXFR位置1,以访问在XDATA区域的扩展SFR
// P0PU |= 0XA0; //设置P0.5,P0.7口有上拉电阻
// P3PU |= 0XC0; //设置P3.6,P3.7口有上拉电阻
// P_SW2 &= 0X7E; //将EAXFR位置0,恢复访问XRAM
//****************************************************************************************//
void main(void)
{
stcIO_Init(); //STC IO 模式设置
iicInit();
laser_Timer0_Init();
//stc8g_pwm_init ();
Timer1_Init();
OLED_Init(); //OLED初始化
int0_Init(); //int0初始化
m=0;
f=0;
TR1=1;
EA=1;
while(1)
{
//p33=0;
//OLED_P6x8Str(0,1,"www.taobao.com");
//OLED_P8x16Str(0,0,"Hello");//第一行 -- 8x16的显示单元显示ASCII码
//OLED_z8x16 (14,2,6);
//OLED_P16x16Ch(24,0,1); /**功能描述:显示16*16点阵 显示的坐标(x,y),y为页范围0~7** void OLED_P16x16Ch(unsigned char x, y, N)**/
//OLED_z17x32 (6,0,k);
scan_key();
if(!mun)
{
do_rpm();
}
if((mun==2)&&ok5104)
{
do_ir5104();
}
switch (mun)
{
case 0:
if(dis[4]!=dis_tmp[4])
{
dis[4]=dis_tmp[4];
OLED_z17x32 (18,0,dis[4]);
}
if(dis[3]!=dis_tmp[3])
{
dis[3]=dis_tmp[3];
OLED_z17x32 (40,0,dis[3]);
}
if(dis[2]!=dis_tmp[2])
{
dis[2]=dis_tmp[2];
OLED_z17x32 (62,0,dis[2]);
}
if(dis[1]!=dis_tmp[1])
{
dis[1]=dis_tmp[1];
OLED_z17x32 (84,0,dis[1]);
}
if(dis[0]!=dis_tmp[0])
{
dis[0]=dis_tmp[0];
OLED_z17x32 (106,0,dis[0]);
}
break;
case 1:
if(irdis[7]!=show[7])
{
irdis[7]=show[7];
OLED_F8x16(30,2,irdis[7]);
}
if(irdis[6]!=show[6])
{
irdis[6]=show[6];
OLED_F8x16(38,2,irdis[6]);
}
if(irdis[5]!=show[5])
{
irdis[5]=show[5];
OLED_F8x16(54,2,irdis[5]);
}
if(irdis[4]!=show[4])
{
irdis[4]=show[4];
OLED_F8x16(62,2,irdis[4]);
}
if(irdis[3]!=show[3])
{
irdis[3]=show[3];
OLED_F8x16(78,2,irdis[3]);
OLED_F8x16(102,0,irdis[3]);
}
if(irdis[2]!=show[2])
{
irdis[2]=show[2];
OLED_F8x16(86,2,irdis[2]);
OLED_F8x16(110,0,irdis[2]);
}
if(irdis[1]!=show[1])
{
irdis[1]=show[1];
OLED_F8x16(102,2,irdis[1]);
}
if(irdis[0]!=show[0])
{
irdis[0]=show[0];
OLED_F8x16(110,2,irdis[0]);
}
break;
case 2:
if(irdis[7]!=show[7])
{
irdis[7]=show[7];
OLED_F8x16(30,2,irdis[7]);
}
if(irdis[6]!=show[6])
{
irdis[6]=show[6];
OLED_F8x16(38,2,irdis[6]);
}
//if(irdis[5]!=show[5]){irdis[5]=show[5];OLED_F8x16(54,2,irdis[5]);}
//if(irdis[4]!=show[4]){irdis[4]=show[4];OLED_F8x16(62,2,irdis[4]);}
if(irdis[3]!=show[3])
{
irdis[3]=show[3];
OLED_F8x16(66,2,irdis[3]);
}
if(irdis[2]!=show[2])
{
irdis[2]=show[2];
OLED_F8x16(74,2,irdis[2]);
}
if(irdis[1]!=show[1])
{
irdis[1]=show[1];
OLED_F8x16(102,2,irdis[1]);
OLED_F8x16(102,0,irdis[1]);
}
if(irdis[0]!=show[0])
{
irdis[0]=show[0];
OLED_F8x16(110,2,irdis[0]);
OLED_F8x16(110,0,irdis[0]);
}
break;
default:
break;
}
if(ir)
{
OLED_F8x16(2,0,36);
}
else
{
OLED_F8x16(2,0,37);
}
//_nop_();
//_nop_();
}
}
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
打赏
-
查看全部打赏
|