找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1436|回复: 10
收起左侧

51单片机求助,求大佬帮忙修改一下代码,注释齐全,实在不知道哪里错了QAQ

[复制链接]
ID:480568 发表于 2019-8-2 20:06 | 显示全部楼层 |阅读模式
100黑币
我想用51单片机做一个盖革计数器,盖革管发出脉冲经过芯片过滤成方波,用外部中断器1进行计数,定时器0定20s通过公式计算一次辐射强度然后通过1602显示,定时器1专门用于延时的定时,不知道为什么老卡在欢迎语那里不动,请大佬指点QAQ这卡了我一个星期卡的好难受啊,以下是代码:
/*********************************************************************
*名称:盖革计数器
*功能:测量电离辐射值
*版本:0.13
*********************************************************************/
#include <reg51.h>
#include "lcd.h"
#define _2s 200     //延时2s
float S;    //单精度数
uint t;     //定义全局变量用于延时计数
uint k;     //定义全局变量用于计算脉冲数
sbit rad  =  P3^2;     //电离计数
sbit beep =  P1^0;     //蜂鸣器引脚
uchar revo[]="   Revolution!  ";     //欢迎语部分
uchar dang[]="     Danger!    ";     //危险辐射报警
uchar radi[]="    Radiation   ";     //辐射值标题
uchar code unit[5]   =    {'u','S','v','/','h'};                             //辐射单位显示数组
uchar code ASCII[11] =    {'0','1','2','3','4','5','6','7','8','9','.'};     //数字显示数组
uchar disbuff[8]    ={0,0,0,0,0,0,0,0};
bit flag = 0;
/*********************************************************************
*名称:定时器模块
*功能:定时器延时及中断
*输入:无
*输出:无
*********************************************************************/
void delayms(uint x)//定时器10毫秒级延时函数
{
t=x;
while(t);
}
void InitTimer0()//定时器0初始化函数(得到20s时间计时)
{
TMOD=0x01;     //定时器0,工作方式1
//定时10ms
TH0 = 0xDC;     //高八位
TL0 = 0x00;     //低八位
ET0= 1;        //打开定时器0中断
EA = 1;        //打开总中断
TR0= 1;        //打开定时器0
}
void InitTimer1()//定时器1初始化函数(延时定时器)
{
TMOD=0x10;     //定时器1,工作方式1
//定时10ms
TH1 = 0xDC;     //高八位
TL1 = 0x00;     //低八位
ET1= 1;        //打开定时器1中断
EA = 1;        //打开总中断
TR1= 1;        //打开定时器1
}
void Timer0() interrupt 1  //定时器1服务函数
{
static uint i;
TH1=0XDC;
TL1=0X00;
i++;
if(i==2000)     //20s计算一次
{
  i=0;
}
}
void Timer1() interrupt 3  //定时器0服务函数
{
TH0 = 0xDC;
TL0 = 0x00;
t--;
}
/*********************************************************************
*名称:显示模块
*功能:lcd1602液晶显示
*输入:无
*输出:无
*********************************************************************/
void welcome()//欢迎语函数
{
InitLcd1602();            //屏幕初始化
LcdShowStr(0,0,revo);     //显示欢迎语
delayms(_2s);
Lcd1602_Write_Cmd(0x01);  //清屏  
LcdShowStr(0,0,radi);     //显示辐射标题
DisplayOneChar(4,1,ASCII[10]);    //显示小数点
DisplayOneChar(11,1,unit[0]);     //显示辐射单位uSv/h
DisplayOneChar(12,1,unit[1]);
DisplayOneChar(13,1,unit[2]);
DisplayOneChar(14,1,unit[3]);
DisplayOneChar(15,1,unit[4]);
}
/*********************************************************************
*名称:外部中断模块
*功能:外部中断计数及危险报警
*输入:无
*输出:无
*********************************************************************/
void Int1Init()
{
//设置INT1
IT1=1;//跳变沿出发方式(下降沿)
EX1=1;//打开INT1的中断允许。
EA=1;//打开总中断
}
void Int1() interrupt 2  //外部中断1的中断函数(测量盖革管脉冲数)
{
delayms(1000);  //延时消抖
if(rad==0)
  ++k;
if(k>65535)
  flag=1;
}
/*********************************************************************
*名称:脉冲计数模块
*功能:盖革计数器脉冲计数
*输入:无
*输出:无
*********************************************************************/
void calculate()
{
  S=k/(1.67*235);
  k=0;
if(S>=9999||flag==1)
{
  Lcd1602_Write_Cmd(0x01);  //清屏
  LcdShowStr(0,0,dang);     //显示危险
  while(1)
  {
   beep=~beep;        //蜂鸣器常响,LED灯常亮
   delayms(1);        //频率尖锐
  }
}
else
{
  long A;
  A=S*10000;
  disbuff[0]=A/10000000;        //千位   
  disbuff[1]=A%10000000/1000000;     //百位
  disbuff[2]=A%1000000/100000;     //十位
  disbuff[3]=A%100000/10000;     //个位
  disbuff[4]=A%10000/1000;     //十分位
  disbuff[5]=A%1000/100;     //百分位
  disbuff[6]=A%100/10;     //千分位
  disbuff[7]=A%10;     //万分位
  
  DisplayOneChar(0, 1, ASCII[disbuff[0]]);
  DisplayOneChar(1, 1, ASCII[disbuff[1]]);
  DisplayOneChar(2, 1, ASCII[disbuff[2]]);
  DisplayOneChar(3, 1, ASCII[disbuff[3]]);
  DisplayOneChar(5, 1, ASCII[disbuff[4]]);
  DisplayOneChar(6, 1, ASCII[disbuff[5]]);
  DisplayOneChar(7, 1, ASCII[disbuff[6]]);
  DisplayOneChar(8, 1, ASCII[disbuff[7]]);
}
}
/*********************************************************************
*名称:main
*功能:盖革计数器
*输入:无
*输出:无
*********************************************************************/
void main()
{
InitTimer0();  //设置定时器0
Int1Init();    //设置外部中断1
InitTimer1();  //设置定时器1

welcome();     //欢迎语
calculate();   //计算辐射强度
}


最佳答案

查看完整内容

我写的电压表的显示欢迎语的函数,实际可以正常操作 unsigned char code mytable1[]="4 Chanel Voltmeter!"; unsigned char code mytable2[]="51hei.com"; ……… void lcdinit(void)//初始化LCD { unsigned char t; delay(300); comm(0x38); delay(100); comm(0x38); delay(100); comm(0x38); delay(100); comm(0x38); comm(0x38); comm(0x08); comm(0x01); comm(0x06); comm(0x0c); comm(0x80) ...
回复

使用道具 举报

ID:97554 发表于 2019-8-2 20:07 | 显示全部楼层
我写的电压表的显示欢迎语的函数,实际可以正常操作



unsigned char code  mytable1[]="4 Chanel Voltmeter!";
unsigned char code  mytable2[]="51hei.com";

………

void lcdinit(void)//初始化LCD
{
unsigned char t;
delay(300);
comm(0x38);
delay(100);
comm(0x38);
delay(100);
comm(0x38);
delay(100);
comm(0x38);
comm(0x38);
comm(0x08);
comm(0x01);
comm(0x06);
comm(0x0c);
        comm(0x80);         
        for(t=0;t<18;t++)         
        {
                LcdDis(mytable1[t]);
                delay(10000);             //语句进入的快慢
        }
                comm(0xc5);           //第二行,从第一格开始显示

        for(t=0;t<9;t++)      
        {
                LcdDis(mytable2[t]);
                delay(10000);            //语句进入的快慢
        }
        delay(50000);
        delay(50000);
        delay(50000);       //这个三个延时决定欢迎语的显示时间长短
        comm(0x01);      //清屏指令  每次显示下一屏内容时,必须清屏
        comm(0x80);  
}


………………

回复

使用道具 举报

ID:97554 发表于 2019-8-3 11:20 | 显示全部楼层
InitLcd1602();   
没发现这个函数

把欢迎语放在这个初始化函数里,加上延时,然后清屏。

显示函数直接显示数据界面应该就OK了
回复

使用道具 举报

ID:97554 发表于 2019-8-3 11:24 | 显示全部楼层
把 lcd.c贴上来,void welcome不需要作为一个函数放在主程序里吧,直接把欢迎语句放在初始化程序里,延时后清屏,然后进入主界面不就完事了吗?
回复

使用道具 举报

ID:88481 发表于 2019-8-3 11:52 来自手机 | 显示全部楼层
在执行定义定时器1初始化时影响了定时器0。应该在定时器1初始化函数中"TMOD=0x10"改为"TMOD |= 0x10"
回复

使用道具 举报

ID:480568 发表于 2019-8-3 14:56 | 显示全部楼层
杨雪飞 发表于 2019-8-3 11:34
我写的电压表的显示欢迎语的函数,实际可以正常操作

好的好的,我试试
回复

使用道具 举报

ID:480568 发表于 2019-8-3 14:57 | 显示全部楼层
883 发表于 2019-8-3 11:52
在执行定义定时器1初始化时影响了定时器0。应该在定时器1初始化函数中"TMOD=0x10"改为"TMOD |= 0x10"

谢谢,我试一下
回复

使用道具 举报

ID:480568 发表于 2019-8-3 14:59 | 显示全部楼层
杨雪飞 发表于 2019-8-3 11:24
把 lcd.c贴上来,void welcome不需要作为一个函数放在主程序里吧,直接把欢迎语句放在初始化程序里,延时后 ...

lcd.c用的是普中给的超声波测距的,我觉得那个比较好用
#include"lcd.h"


void Read_Busy()           //忙检测函数,判断bit7是0,允许执行;1禁止
{
    unsigned char sta;      //
    LCD1602_DB = 0xff;
    LCD1602_RS = 0;
    LCD1602_RW = 1;
    do
    {
        LCD1602_EN = 1;
        sta = LCD1602_DB;
        LCD1602_EN = 0;    //使能,用完就拉低,释放总线
    }while(sta & 0x80);
}

void Lcd1602_Write_Cmd(unsigned char cmd)     //写命令
{
    Read_Busy();
    LCD1602_RS = 0;
    LCD1602_RW = 0;
    LCD1602_DB = cmd;
    LCD1602_EN = 1;
    LCD1602_EN = 0;   
}

void Lcd1602_Write_Data(unsigned char dat)   //写数据
{
      Read_Busy();
      LCD1602_RS = 1;
      LCD1602_RW = 0;
      LCD1602_DB = dat;
      LCD1602_EN = 1;
      LCD1602_EN = 0;
}

void LcdSetCursor(unsigned char x,unsigned char y)  //坐标显示
{
    unsigned char addr;
    if(y == 0)
        addr = 0x00 + x;
    else
        addr = 0x40 + x;
   
    Lcd1602_Write_Cmd(addr|0x80);
}

//按指定位置显示一个字符
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
{
        Y &= 0x1;
        X &= 0xF; //限制X不能大于15,Y不能大于1
        if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;
        X |= 0x80; //算出指令码
        Lcd1602_Write_Cmd(X); //发命令字
        Lcd1602_Write_Data(DData); //发数据
}


void LcdShowStr(unsigned char x,unsigned char y,unsigned char *str)     //显示字符串
{
    LcdSetCursor(x,y);      //当前字符的坐标
    while(*str != '\0')
    {
        Lcd1602_Write_Data(*str++);
    }
}

void InitLcd1602()              //1602初始化
{
    Lcd1602_Write_Cmd(0x38);    //打开,5*8,8位数据
    Lcd1602_Write_Cmd(0x0c);
    Lcd1602_Write_Cmd(0x06);
    Lcd1602_Write_Cmd(0x01);    //清屏   
}
回复

使用道具 举报

ID:480568 发表于 2019-8-3 15:04 | 显示全部楼层
883 发表于 2019-8-3 11:52
在执行定义定时器1初始化时影响了定时器0。应该在定时器1初始化函数中"TMOD=0x10"改为"TMOD |= 0x10"

我后来直接删除了定时器1的运用,直接用普通的while来做延时,但是还是卡在最开始显示的地方啊。。。
回复

使用道具 举报

ID:213173 发表于 2019-8-4 05:54 | 显示全部楼层
void main()
{
InitTimer0();  //设置定时器0
Int1Init();    //设置外部中断1
InitTimer1();  //设置定时器1

welcome();     //欢迎语
calculate();   //计算辐射强度
}
楼主这样写主程序是无法正常运行的,MCU永远处于重复不断的初始化状态。
回复

使用道具 举报

ID:480568 发表于 2019-8-5 16:24 | 显示全部楼层
wulin 发表于 2019-8-4 05:54
void main()
{
InitTimer0();  //设置定时器0

呃呃。。。刚学的定时器和计数器,那大佬有什么好方法吗?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表