在《CAP功能测频率》一文中,我们讲了利用STC12C5608AD的CAP功能测量频率,这一节,我们讲利用CAP功能测量频率的占空比,下面的程序,是我在做一个显示汽车发动机点火喷油脉宽项目时做的程序。现在分享给大家:
/************************************************************************** 功能:测量频率的低电平保持时间,用来测量汽车喷油嘴喷油的时间,单位ms 硬件:STC12C5608AD+3位LED+TM1620+12M晶振+LM358+74HC14 ****************************************************************************/ #include// 调用头文件,可以上官方下载STC12C5608AD下载头文件 #include #include //因为本例中,有用到modf;所以必须调用该头文件 #define uint unsigned int // 宏定义uint (0~65535) #define uchar unsigned char // #define WAIT_TIME 0x01 //mcu clock <24mhz // 定义Flash 操作等待时间 #define OPENUART 0 // 0 关闭串口, 1 打开串口 sbit STB =P3^2; // 定义片选通讯口 sbit CLK =P3^3; // 定义时钟通讯口 sbit DIO =P3^4; // 定义数据输入/输出通讯口 sbit CheSu1 = P3^5; // 测试速度的引脚 sbit KEY1 = P1^7; uchar bai_num,shi_num,ge_num; uint CheSu;//表示低电平的时间,单位10us //uint CS_F=0; // 上一个车速寄存器 uchar CheSu_Clr=0; unsigned int cap_tmp; //float xielv=1.0; // 车速与车速频率的斜率 //float chesu_f; //uchar CheSu_error[5]={0}; //uchar cse_cnt=0; //uchar jiao=0; // 车速校正开关 static uchar code LED_tab[12]={ // 定义数码管0~9数字码表 0x3f, //0B00111111, //0 0x06, //0B00000110, //1 0x5b, //0B01011011, //2 0x4f, //0B01001111, //3 0x66, //0B01100110, //4 0x6d, //0B01101101, //5 0x7d, //0B01111101, //6 0x07, //0B00000111, //7 0x7f, //0B01111111, //8 0x6f, //0B01101111, //9 0x40, //- 0x00 }; unsigned char out_data[2]={0x00}; void delay_ms(uint cyc) { //当将=1的时候,延时1ms uint ii,jj; for(jj=1;jj<=cyc;jj++) { for(ii=0;ii<940;ii++) { _nop_(); } } } void TM1620_Write(uchar wr_data) { uchar i; for(i=0;i<8;i++) { CLK = 0; if(wr_data&0x01)DIO = 1; else DIO = 0; CLK = 1; wr_data>>=1; } } void Write_COM(unsigned char cmd) //发送命令字 { STB = 0; TM1620_Write(cmd); STB = 1; } void init_TM1620(void) { Write_COM(0x44); // 01000000准备写数据到显示寄存器,普通模式,自动地址增加 STB=0; TM1620_Write(0xc0); // 11000000 设置显示地址从0开始 TM1620_Write(0x00); // 所有显示为灭 STB=1; STB=0; TM1620_Write(0xc2); TM1620_Write(0x00); STB=1; STB=0; TM1620_Write(0xc4); TM1620_Write(0x00); STB=1; Write_COM(0x8a); // 最亮 10001111 设置消光脉冲14/16 显示开 } void led_show() { // Write_COM(0x44); // 01000000准备写数据到显示寄存器,普通模式,自动地址增加 STB=0; TM1620_Write(0xc0); // 11000000 设置显示地址从0开始 TM1620_Write(LED_tab[bai_num]); // 所有显示为灭 STB=1; STB=0; TM1620_Write(0xc2); // 11000000 设置显示地址从0开始 TM1620_Write(LED_tab[shi_num]); // 所有显示为灭 STB=1; STB=0; TM1620_Write(0xc4); // 11000000 设置显示地址从0开始 TM1620_Write(LED_tab[ge_num]); // 所有显示为灭 STB=1; } void CAP_Init(void) { // T0、T1打开,T0做PCA时钟,T1做定时器,在中断里喂狗和给CheSu清零 TMOD=0x12; // T0工作在8位自动重载模式,T1工作在16位模式 TH0=0XF6; //12M下的值,10us TL0=0XF6; TR0=1; TH1=0X00; TL1=0X00; ET1=1; TR1=1; // PCA计数器打开 CMOD = 0X04; // 选择T0的溢出为PCA计数时钟 CCAPM1 = 0X11; // CAPN0 = 1; 下降沿捕获。ECCF0 = 1; 开捕获中断。 CL = 0; CH = 0; // PCA计数器清零 CCAP1L = 0; CCAP1H = 0; // 捕获寄存器清零 EPCA_LVD = 1; // 开PCA中断 // CR = 1; } /********************************************************************/ /********************** T1中断服务函数 ****************************/ /********************************************************************/ // 65.536毫秒进一次中断 void T1_SER() interrupt 3 { CheSu_Clr++; WDT_CONTR=0x3C; // 1.1377s不喂狗复位 if(CheSu_Clr>=17) // 1秒钟没有进PCA中断函数清CheSu_Clr,车速归0 { out_data[0]=0; out_data[1]=0; CheSu_Clr=0; // 车速为0标志 CheSu=0; } } // PCA中断服务函数 void PCAIRQ(void) interrupt 6 { if(CCF1==1) // 如果是PCA1捕获产生的中断 { CCF1=0; if(CCAPM1==0X11) { CR = 1; // 打开PCA计数器 CCAPM1 = 0X21;// 配置为上升沿触发中断 } else { CR = 0;// 关闭PCA计数器 CCAPM1 = 0X11; // 配置为下降沿触发中断 out_data[0]=CCAP1L; out_data[1]=CCAP1H; CH=0; CL=0; // 获取当前低电平保持时间数据 cap_tmp=out_data[1]<<8; cap_tmp+=out_data[0]; CheSu = cap_tmp; } } else if(CF==1) // 如果是PCA溢出产生的中断 { CF = 0; } CheSu_Clr=0; } void led_xian(uint led_val) { if(led_val<1000) // 小于1000,显示为0.00格式,单位毫秒 { bai_num=(led_val/100); shi_num=(led_val%100)/10; ge_num=(led_val%100)%10; STB=0; TM1620_Write(0xc0); // 11000000 设置显示地址从0开始 TM1620_Write(LED_tab[bai_num]|0x80); // 所有显示为灭 STB=1; STB=0; TM1620_Write(0xc2); // 11000000 设置显示地址从0开始 TM1620_Write(LED_tab[shi_num]); // 所有显示为灭 STB=1; STB=0; TM1620_Write(0xc4); // 11000000 设置显示地址从0开始 TM1620_Write(LED_tab[ge_num]); // 所有显示为灭 STB=1; } else // 大于等于1000,显示为00格式,单位毫秒 { bai_num = 11; shi_num = (led_val/100)/10; ge_num = (led_val/100)%10; led_show(); } } void main() { unsigned int ms_cnt=0; CLK = 1; // 上拉TM1629B通信时钟引脚 STB = 1; // 上拉TM1629B通信片选引脚 DIO = 1; // 上拉TM1629B通信数据引脚 init_TM1620(); // 初始化LED控制芯片 bai_num=11; shi_num=11; ge_num=0; led_show(); delay_ms(1200); CAP_Init(); EA = 1; while(1) { ms_cnt++; delay_ms(1); if(ms_cnt>300) // 300毫秒显示一次数据 { ms_cnt=0; if(CheSu<1000) { led_xian(CheSu); } } } }
上一篇:stc51单片机硬件SPI驱动nrf24l01程序
下一篇:51单片机驱动1602程序
推荐阅读最新更新时间:2024-03-16 15:24