51单片机脉冲信号的计数和LCD显示
设计目标和思路
在个人剂量仪开发的过程中,从探头输出的核脉冲信号经过后期放大,成形,滤波以及甄别之后,成为一系列脉冲信号输出,这种脉冲信号由于衰变的随机性,并不是固定频率的脉冲信号。我们本次设计就是针对这种脉冲进形脉冲信号的计数以及在LCD1602显示屏上面的显示。
这是C语言的代码部分
#include"reg51.h"
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <intrins.h>
#define uint8_t unsigned char //0-255
#define uint16_t unsigned int //0-65535
#define uint32_t unsigned long //0-4294967295
#define uchar unsigned char
#define u8 unsigned char
#define u16 uint16_t
#define uchar unsigned char
#define uint unsigned int
unsigned long millis = 0; //1MS¼ÆÊý
sbit rs = P2^0; //LCD1602 RS
sbit rw = P2^1; //LCD1602 RW
sbit en = P2^2; //LCD1602 EN
sbit Input1 = P3^2; //定义P32为第一路脉冲输入
uint8_t Input_1_Last_V = 0;
uint16_t Input_1_Count = 0;
sbit Input2 = P3^3; //定义P33为第二路脉冲输入
uint8_t Input_2_Last_V = 0;
uint16_t Input_2_Count = 0;/
sbit Key1 = P1^0; //这个向下翻
sbit Key2 = P1^1; //向上翻按键
#define display_Flag_Jishu_CH1_CH2 1 //
#define display_Flag_Jishu_DY 2
#define MIN_Display_flag display_Flag_Jishu_CH1_CH2
#define MAX_Display_flag display_Flag_Jishu_DY
uint8_t display_Mode_or_Set = 0;
uint8_t display_Flag = 1;
uint8_t display_sec = 0;
uint8_t jishu_sec = 0;
uint16_t CH_Count_Buffer[30];
uint8_t Count_D = 0;
*******************************************************************************/
void delay(uint8_t i)
{
while(i--);
}
void delay_1s(uint8_t s)
{
unsigned int i;
unsigned char j;
while(s--)
for (i = 1000; i > 0; i--)
for (j = 124; j > 0; j--) ;
}
/*******************************************************************************
* 这段程序很容易找到 : LCD初始化
*******************************************************************************/
void lcd_wcom(uint8_t com) //LCD1602 写命令
{
rs = 0;
rw = 0;
en = 0;
P0 = com;
delay(100);
en = 1;
delay(100);
en = 0;
}
void lcd_wdat(uint8_t dat) //LCD1602写数据
{
rs = 1;
rw = 0;
en = 0;
P0 = dat;
delay(100);
en = 1;
delay(100);
en = 0;
}
void lcd_init(void) //LCD1602初始化
{
lcd_wcom(0x38);
lcd_wcom(0x0c);
lcd_wcom(0x06);
lcd_wcom(0x01);
}
/***********************************************************************
/**********************************************************************
*******************************************************************************/
void Timer_Init(void) //
{
TMOD |= 0x01;
TH0 = 0xFC;
TL0 = 0x18;
EA = 1;
ET0 = 1;
TR0 = 0;/
}
/***********************************************************************
一路脉冲显示数值
*******************************************************************************/
void ReadInput(void)
{
if(Input1 == 0)
{
Input_1_Last_V = 0;
}
else if((Input1 == 1)&&(Input_1_Last_V == 0))
{
Input_1_Last_V = 1;
Input_1_Count++;
}
//第二路脉冲显示计数值
if(Input2 == 0)
{
Input_2_Last_V = 0;
}
else if((Input2 == 1)&&(Input_2_Last_V == 0))
{
Input_2_Last_V = 1;
Input_2_Count++;
}
}
/***********************************************************************
LCD显示程序
*******************************************************************************/
void LCD_DisPlay_Jishulv_CH1_CH2(void)
{
lcd_wcom(0x80);
lcd_wdat('C');
lcd_wdat('H');
lcd_wdat('1');
lcd_wdat(':');
lcd_wdat((Input_1_Count%100000/10000) +'0');//万
lcd_wdat((Input_1_Count%10000/1000) +'0');//千
lcd_wdat((Input_1_Count%1000/100) +'0');//百
lcd_wdat((Input_1_Count%100/10) +'0');//十
lcd_wdat((Input_1_Count%10) +'0');//个
//通道2显示
lcd_wcom(0x80+0x40);
lcd_wdat('C');
lcd_wdat('H');
lcd_wdat('2');
lcd_wdat(':');
lcd_wdat((Input_2_Count%100000/10000) +'0');//万
lcd_wdat((Input_2_Count%10000/1000) +'0');//千
lcd_wdat((Input_2_Count%1000/100) +'0');//百
lcd_wdat((Input_2_Count%100/10) +'0');//十
lcd_wdat((Input_2_Count%10) +'0');//个
}
/***********************************************************************
LCD显示自检程序
*******************************************************************************/
void Display_Checking(void)
{
lcd_wcom(0x80);
lcd_wdat('C');
lcd_wdat('h');
lcd_wdat('e');
lcd_wdat('c');
lcd_wdat('k');
lcd_wdat('i');
lcd_wdat('n');
lcd_wdat('g');
}
void Display_CheckFall(void)//自检失败
{
lcd_wcom(0x80+0x40);
lcd_wdat('C');
lcd_wdat('h');
lcd_wdat('e');
lcd_wdat('c');
lcd_wdat('k');
lcd_wdat(' ');
lcd_wdat('F');
lcd_wdat('a');
lcd_wdat('i');
lcd_wdat('l');
}
void Display_CheckOk(void)//自检成功
{
lcd_wcom(0x80+0x40);
lcd_wdat('C');
lcd_wdat('h');
lcd_wdat('e');
lcd_wdat('c');
lcd_wdat('k');
lcd_wdat(' ');
lcd_wdat('O');
lcd_wdat('K');
}
/***********************************************************************
动态显示
*******************************************************************************/
void Display(uint8_t display_Flag)
{
switch (display_Flag)
{
case display_Flag_Jishu_CH1_CH2:
LCD_DisPlay_Jishulv_CH1_CH2();
break;
}
}
/***********************************************************************
按键子程序
*******************************************************************************/
void Button_Handler()//按键函数
{
if(display_Mode_or_Set == 0) //设置模式
{
if(Key1 == 0) //当按键1被按下
{
if(display_Flag>MIN_Display_flag)
{
display_Flag--;
lcd_wcom(0x01);
Display(display_Flag);
}
while(Key1 == 0);
}
if(Key2 == 0) //当按键2被按下
{
if(display_Flag<MAX_Display_flag)
{
display_Flag++;
lcd_wcom(0x01);
Display(display_Flag);
}
while(Key2 == 0);
}
}
}
/***********************************************************************
动态显示处理函数
*******************************************************************************/
void Display_Handler(void)
{
if(display_Mode_or_Set == 0)
{
if(display_sec == 1)
{
Display(display_Flag);
display_sec = 0;
}
}
}
/***********************************************************************
计数满30组更换
*******************************************************************************/
void DataHandler(void) //计数率统计
{
static uint8_t firstTime = 1;//第一组不计算
uint8_t i = 0;
uint16_t last_Count = 0;
uint16_t now_Count = 0;
if(jishu_sec == 1)
{
for(i=0;i<30;i++)
{
//不满30组填入空白数据
if(CH_Count_Buffer[i] == 0)
{
CH_Count_Buffer[i] = Input_1_Count+Input_2_Count;
now_Count = Input_1_Count+Input_2_Count;
if(i == 0)
{
firstTime = 1;
}
else
{
last_Count = CH_Count_Buffer[i-1];
}
break;
}
}
if(i == 30) //计数满30组
{
for(i=0;i<29;i++)
{
CH_Count_Buffer[i] = CH_Count_Buffer[i+1];
}
last_Count = CH_Count_Buffer[28];
CH_Count_Buffer[29] = Input_1_Count+Input_2_Count;
now_Count = Input_1_Count+Input_2_Count;
}
if(firstTime == 1)
{
firstTime = 0;
}
else
{
if((now_Count>=(last_Count*10))||(last_Count>=(now_Count*10)))
{
LED = 0;
for(i = 0;i<30;i++)
CH_Count_Buffer[i] = 0;
CH_Count_Buffer[0] = now_Count;
}
}
Input_1_Count = 0;
Input_2_Count = 0;
jishu_sec = 0;
}
}
/***********************************************************************
进行自检
*******************************************************************************/
uint8_t self_checking() //自检程序
{
uint16_t self_check_buffer[3];
unsigned char xdata system_status=0;
u8 JLZ=0;
u8 JLL=0;
uint8_t i = 0;
uint8_t a = 1;
u8 b=0;
uint8_t count = 0;
float v=0.3;
TR0 = 1; //打开定时器
while(i<3)
{
ReadInput();
if(jishu_sec ==1) //1S
{
jishu_sec = 0;
self_check_buffer[i] = Input_1_Count+Input_2_Count;
Input_1_Count = 0;
Input_2_Count = 0;
i++;
}
}
判断自检是否成功
for(count= 0;count<3;count++)
{
if((self_check_buffer[count]<1)||(self_check_buffer[count]>10000))
{
TR0 = 0;
return 0;
}
}
TR0 = 0;
return 1;
}
/***********************************************************************
主函数
*******************************************************************************/
void main()
{
u16 ad;
uint8_t i = 0;
lcd_init(); //LCD初始化
Timer_Init(); //定时器初始化
Display_Checking();//开始自检
if(self_checking() == 1)
Display_CheckOk();//当自检成功
else
{
Display_CheckFall();
while(1);//完成之后下一步
}
delay_1s(10);
TR0 = 1; //打开定时器
while(1) //
{
ReadInput();//读取输入
Button_Handler(); //按键函数
Display_Handler(); //显示函数
DataHandler(); //数据函数
delay(10);
}
i++;
}
}
定时器函数
void trigger_timer0() interrupt 1
{
TH0 = 0xFC;
TL0 = 0x18;
millis++;
if(millis%1000 == 0)
{
display_sec = 1;
jishu_sec = 1;
}
}
write by 亦舒斋
交流联系QQ:1464475872