限时定数法——简易高精度转速表,曾经的课程设计
2016-10-06 03:37
239 查看
大学二年级时的一个课程作业,怀念那些年岁月匆匆,贴出来怀缅
有程序和程序流程图,高转速时信号调理电路对边沿的处理较为重要,硬件需注意,信号须同时传到单片机INT0和T1计数IO口简述:基于限时定数法,51平台所谓“单时钟周期”12MHz,C语言源码非汇编,传感器6脉冲每转,5转/分钟至300000转/分钟范围内,相对误差小于0.0125%,LCD1602显示
//崔廷佐 转速范围:5RPM-300000RPM 相对误差小于0.0125% 传感转盘每转脉冲数:6 //单片机平台:STC12C5A60S2 1T @12MHz //2014.5.25 原创 //信号调理由实验台完成,输入接INT0、T1引脚,注意使用外围电路对输入电平箝位,防止外部相对电势差过大损坏IO引脚 //要求单片机要有一定的处理速度,外部中断后的250μs内要完成本程序的一次中断子程序 //为求较高精度,读数变更较慢,在新的计算周期,第一个脉冲到来时刻起,经两秒再过一个脉冲“立即”暂停所有计数,采集圈数及时间值进行换算,更新一次读数 //大约两秒没有信号接入,显示“No Access”(任何仪器计数频率都无法做到无穷趋近零,即周期无法是无穷大,通常也不现实,本课程设计为简易设计,作此侧重) #include <reg52.h> #include <stdio.h> typedef unsigned int uint; typedef unsigned char uchar; sbit RS=P0^2; //LCD1602并行,6800总线 sbit RW=P0^1; sbit E=P0^0; #define Data_Port P1 //6800总线数据口使用P1口 volatile bit data Flag_2s=0; //两秒标志 volatile bit data Flag_Read=0; //读取标志 volatile bit data Flag_again=1; //开始计时、计数标志 volatile bit data Flag_No_Access=0; //“无接入”标志 uchar data Turn_Cnt_M8b=0; //转速计数高八位 uchar data Turn_Cnt_L8b=0; //转速计数低八位 uchar data Oth_time_Cnt_50ms=0; //额外时间50ms计数,缓冲单元 uchar data Oth_time_Cnt_250us=0; //额外时间,250us计数,缓冲单元 uint data Cnt_No_Access1=0; //“无接入”计数 uint data Cnt_No_Access2=0; //“无接入”计数 uchar data Cnt_50ms=0; //50ms计数值 uchar data Cnt_250us=0; //250us计数值 uchar data Time0_50ms=0; //定时器50ms计数值 uchar data Time0_250us=0; //定时器250us计数值 float data Min_Turn_Speed=0; //分转速 uchar data num_of_turns_show[]={"T:\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"}; uchar data student[]={"CUI YourName "}; uchar data Turn_String[]={"0.00RPM\x20\x20\x20\x20\x20\x20\x20"}; uchar code Prompt_String[]={"No Access\x20\x20\x20\x20\x20"}; uchar code Turn_String_Space[10][10]={ {""}, {"\x20"}, {"\x20\x20"}, {"\x20\x20\x20"}, {"\x20\x20\x20\x20"}, {"\x20\x20\x20\x20\x20"}, {"\x20\x20\x20\x20\x20\x20"}, {"\x20\x20\x20\x20\x20\x20\x20"}, {"\x20\x20\x20\x20\x20\x20\x20\x20"}, {"\x20\x20\x20\x20\x20\x20\x20\x20\x20"} }; void Init_Time0(void); //函数声明 void Init_Counter1(void); void Init_Int0(void); void delay40us(void); void write(uchar del); void enable(uchar del); void L1602_init(void); void L1602_char(uchar hang,uchar lie,char sign); void L1602_string(uchar hang,uchar lie,uchar *p); void Init_Time0(void) { TMOD=(TMOD&0xf0)|0x02; //T0工作在定时器方式二,自动重装,最大程度确保定时精度(没有方式一严重的总填数时间隙) TL0=0x06; //初值,STC12C5A60S2@12MHz,定时器12分频,250μs TH0=0x06; PT0=0; //优先级为低 ET0=1; //开定时器0中断 TR0=0; //暂不开定时器0 } void Init_Counter1(void) { TMOD=(TMOD&0x0f)|0x50; //T1工作在计数器方式一 TR1=0; //暂不开计数器1 } void Init_Int0(void) { IT0=1; //下降沿中断 PX0=1; //优先级为高 EX0=1; //开外部中断 } int main (void) { uchar String_len=0; Init_Time0(); //初始化定时器0 Init_Counter1(); //初始化计数器1 Init_Int0(); //初始化外部中断0 L1602_init(); //初始化1602 EA=1; //开总中断 L1602_string(1,1,num_of_turns_show); //界面 L1602_string(1,3,Turn_String); L1602_string(2,1,student); while(1) { if(Cnt_No_Access1++>=1000) //超 d4cb 时计数 { Cnt_No_Access1=0; Cnt_No_Access2++; if(Cnt_No_Access2>=1000) { Cnt_No_Access2=0; Flag_No_Access=1; } } if(Flag_No_Access) { L1602_string(1,3,Prompt_String); } else if(Flag_Read) //可以读取 { TR0=0; //关定时器0 TR1=0; //关计数器1 Min_Turn_Speed=10000.0*(((((uint)Turn_Cnt_M8b<<8)|Turn_Cnt_L8b))/(2000.0+(Oth_time_Cnt_250us*0.25+Oth_time_Cnt_50ms*50.0))); //换算 String_len=sprintf(Turn_String,"%-0.2f""RPM",Min_Turn_Speed); //打印并获取字符串长度 L1602_string(1,3+String_len,Turn_String_Space[13-String_len]); //先补空格,盖字^_^ L1602_string(1,3,Turn_String); //显示转速 Flag_Read=0; //清读取标志 Flag_again=1; //置可开始计数计时标志 } else; } return 0; } void Int_0 () interrupt 0 { Cnt_No_Access1=0; //清所有超时标志 Cnt_No_Access2=0; Flag_No_Access=0; if(Flag_again==1) //重入 { TH1=0; //清计数值 TL1=0; Cnt_50ms=0; //清时间积累值 Cnt_250us=0; TL0=0x06; //初值,STC12C5A60S2@12MHz,定时器12分频,250μs TH0=0x06; TR0=1; //开定时器0 TR1=1; //开计数器1,舍弃第一个下降沿 Flag_again=0; //清开始计时计数标志 } if(Flag_2s) //两秒时或两秒后的下降沿到 { TR1=0; //关计数器1 TR0=0; //关计时器 Turn_Cnt_M8b=TH1; //装入两秒内计数值高八位 Turn_Cnt_L8b=TL1; //装入两秒内计数值低八位 Oth_time_Cnt_50ms=Cnt_50ms; //装入其余50ms累计数 Oth_time_Cnt_250us=Cnt_250us; //装入其余250us累计数 Flag_Read=1; //置读取标志 Flag_2s=0; //清两秒标志 TH1=0; //清计数值 TL1=0; Cnt_50ms=0; //清时间积累值 Cnt_250us=0; } } void Timer_0_Int(void) interrupt 1 { Cnt_250us++; //250μs计数自加,250μs为计时精度 if(Cnt_250us==200) //50ms到 { Cnt_250us=0; //清250μs计时值 Cnt_50ms++; //50ms计时值自加 if(Cnt_50ms==40) { Cnt_50ms=0; //清50ms计时值 Flag_2s=1; //置两秒标志,计时误差来自最后一次中断后的处理时间,中间的计时误差不积累 } } } void delay40us(void) //误差 0us,STC12C5A60S2@12MHZ,时钟无分频 { unsigned char a; for(a=117;a>0;a--); } void enable(uchar del) { Data_Port = del; RS = 0; RW = 0; E = 0; delay40us(); E = 1; delay40us(); } void write(uchar del) { Data_Port = del; RS = 1; RW = 0; E = 0; delay40us(); E = 1; delay40us(); } void L1602_init(void) { enable(0x01); enable(0x38); enable(0x0c); enable(0x06); enable(0xd0); } void L1602_string(uchar hang,uchar lie,uchar *p) { uchar a; if(hang == 1) a = 0x80; if(hang == 2) a = 0xc0; a = a + lie - 1; enable(a); while(1) { if(*p !='\0') write(*p); else break; p++; } }
作业上的方案选型和要求(固定格式要求,感觉老师们萌萌哒)
方案一:使用“定时记数法”,在固定的时间T内,利用计数器记录转速传感器发出的脉冲数N,从而算出转速n=N/T。方案优缺点:此方案简单易行。但当固定时间T时刻到来,有可能计数器即将记录到下一个脉冲,因此该方案最大的误差是一个脉冲,一般只适合高转速测量场合。
方案二:使用“记数查时法”,是指用计数器记录固定个脉冲数K,查询记录K个脉冲所花费的时间T,从而计算出转速n=K/T。
方案优缺点:此方案简单易行。但由于定时器最小时间单位往往没有设计中期望的小,当记录K个脉冲所花费的时间T不是足够大时,可能出现测量超差。因此,此方法一般只适用于低转速测量场合。
方案三:采用新的“限时定数法”。
方案优缺点:新的软件算法结合记数查时法和定时计数法的特点,回避了两种算法的缺点。与定时计数法相比,它不是在固定的时间T到后立即取出计数器中的计数来计算转速,而是等到下一个脉冲的下降沿到来时,再进行N/t计算,此举解决了定时计数法可能有一个脉冲误差的问题。与计数查时法相比较,该算法不是记录固定个脉冲后立即进行K/t运算,而是等待t大于某个时间阈值再进行转速运算,解决了记数查时法当转速过高时,记录K个脉冲所用的时间太短而造成的测量超差问题。
方案选择:综合速度和精度考虑,选择方案三为设计方案。具体方案的设计…
…
…
CSDN没办法贴Visio框图,直接PNG图片~
![主函数框图" title="">
主函数框图
![定时器中断框图" title="">
定时器中断框图
![计数框图" title="">
计数框图
![外部中断框图" title="">
外部中断框图
————————☺————————
相关文章推荐
- JAVA基础课程设计 简易扫雷
- 数据结构课程设计---用Dijkstra算法实现一个简易的最佳方案选择
- 编译原理 - 课程设计(简易语法分析器)
- 商务PPT设计制作专题课程,历史最低大专题折上四折(相当于2折哦),限时特惠!
- 编译原理 - 课程设计(简易词法分析器)
- 单片机课程设计—简易频率计—课程设计任务书
- 大一第一学期c语言课程设计,黑框框简易版学生信息管理系统
- 初学java 课程设计ATM机 简易系统(卡片布局)
- 51单片机课程设计:基于GSM的简易手机设计
- 课程设计-简易学生信息管理系统
- 数据结构课程设计-家谱系统的简易开发
- 课程管理系统设计(windows系统)
- 数据结构课程设计——猴子吃桃问题
- 校园导游图的课程设计(零)
- 2013 数据结构课程设计(烟台公交系统)
- 利用不相交集类制作迷宫游戏(数据结构课程设计——迷宫老鼠)
- 算法分析与设计课程——LeetCode刷题之Remove Duplicates from Sorted Array
- [课程设计]Scrum 2.3 多鱼点餐系统开发进度 (订单一览设计)
- 图书管理系统(c语言课程设计)
- 算法分析与设计课程总结