找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 8294|回复: 2
收起左侧

求大神画主程序流程图,各分程序的流程图

[复制链接]
ID:209558 发表于 2018-5-5 18:29 | 显示全部楼层 |阅读模式
50黑币
121.png
#include <reg52.h>
#define uchar unsigned char  //无符号字符型 宏定义 变量范围0~255
#define uint  unsigned int  //无符号整型 宏定义 变量范围0~65535
#include <intrins.h>
#include "eepom52.h"
sbit SCL=P1^4;  //SCL定义,连接ADC0832SCL脚
sbit DO=P1^3;  //DO定义,连接ADC0832DO脚
sbit CS=P1^5;  //CS定义,连接ADC0832CS脚
sbit beep = P3^3;  //蜂鸣器

//这三个引脚参考资料
sbit rs=P1^0;  //1602数据/命令选择引脚 H:数据       L:命令
sbit rw=P1^1;  //1602读写引脚          H:数据寄存器   L:指令寄存器
sbit e =P1^2;  //1602使能引脚          下降沿触发
sbit c_send   = P1^6;  //超声波发射
sbit c_recive = P1^7;  //超声波接收
uchar flag_hc_value;        //超声波中间变量
long distance;             //距离
uint set_d;                 //距离
bit flag_csb_juli;          //超声波超出量程
uint  flag_time0;           //用来保存定时器0的时候的
bit flag_300ms = 1 ;
uchar guangxian;            //光线的显示变量
uchar set_gx;     //设置光线的强弱的变量
uchar value;
uchar flag_alarm;       //报警变量
static int  miao = 0,fen=45;//学习时间
uchar xuexi_start;   //开始学习标志位
uchar menu_1;//菜单设计变量
/******************把设置数据保存到单片机内部eepom中******************/
void write_eepom_12()
{
SectorErase(0x2000);
byte_write(0x2000, set_d % 256);//低8位
byte_write(0x2001, set_d / 256);//高8位距离分解写入
byte_write(0x2002, set_gx);
byte_write(0x2057, value);
}
/******************把数据从单片机内部eepom中读出来*****************/
void read_eepom12()
{
set_d = byte_read(0x2001);
set_d  =set_d * 256 + byte_read(0x2000);  
set_gx = byte_read(0x2002);
value    = byte_read(0x2057);
}
/**************开机自检eepom初始化*****************/
void init_eepom()
{
read_eepom12();  //先读出保存的数据
if(value != 2)  //新的单片机初始单片机内问EEPOM
{
  set_d = 15;//设置超声波的距离
  value = 2;
  set_gx = 4;
  write_eepom_12();
}
}

/********************************************************************
* 名称 : delay()
* 功能 : 延时,延时时间大概为5US。
* 输入 : 无
* 输出 : 无
***********************************************************************/
void delay_uint(uint q)
{
while(q--);
}
/********************************************************************
* 名称 : bit Busy(void)
* 功能 : 这个是一个读状态函数,读出函数是否处在忙状态
* 输入 : 输入的命令值
* 输出 : 无
***********************************************************************/
bit busy(void)
{
bit busy_flag = 0;
rs = 0;
rw = 1;
e = 1;
delay_uint(3);
busy_flag = (bit)(P0 & 0x80);
e = 0;
return busy_flag;
}
/********************************************************************
* 名称 : write_com(uchar com)
* 功能 : 1602命令函数
* 输入 : 输入的命令值
* 输出 : 无
***********************************************************************/
void write_com(uchar com)
{
while(busy());
e=0;
rs=0;
rw=0;
P0=com;
delay_uint(3);
e=1;
delay_uint(25);
e=0;
}
/********************************************************************
* 名称 : write_data(uchar dat)
* 功能 : 1602写数据函数
* 输入 : 需要写入1602的数据
* 输出 : 无
***********************************************************************/
void write_data(uchar dat)
{
while(busy());
e=0;
rs=1;
rw=0;
P0=dat;
delay_uint(3);
e=1;
delay_uint(25);
e=0;
}
/***********************lcd1602上显示两位十进制数************************/
void write_sfm2(uchar hang,uchar add,uchar date)
{
if(hang==1)   
  write_com(0x80+add);
else
  write_com(0x80+0x40+add); //第二行地址   
write_data(0x30+date/10%10); //十位
write_data(0x30+date%10); //个位
}
/***********************lcd1602上显示超声波距离************************/
void write_sfm_csb(uchar hang,uchar add,uint date)
{
if(hang==1)   
  write_com(0x80+add);
else
  write_com(0x80+0x40+add);   
write_data(0x30+date/100%10);
write_data('.');
write_data(0x30+date/10%10);
write_data(0x30+date%10);
}

/********************************************************************
* 名称 : init_1602()
* 功能 : 1602初始化,请参考1602的资料
* 输入 : 无
* 输出 : 无
***********************************************************************/
void init_1602()
{
write_com(0x38); //设置16*2显示,5*7点阵,8位数据接口
write_com(0x0c); //开显示,不显示光标
write_com(0x06); //地址加1,当写入数据的时候光标右移
}
/********************************************************************
* 名称 : write_string(uchar hang,uchar lie,uchar *p)
* 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符开始显示"ab cd ef" ,调用该函数如下
    write_string(1,5,"ab cd ef;")
* 输入 : 行,列,需要输入1602的数据
* 输出 : 无
***********************************************************************/
void write_string(uchar hang,uchar add,uchar *p)
{
if(hang==1)   
  write_com(0x80+add);
else
  write_com(0x80+0x40+add);
  while(1)               
  {
   if(*p == '\0')  break;
   write_data(*p);
   p++;
  }
}
uchar key_can;
/********************独立按键程序*****************/
void key()
{
static uchar key_new;
key_can = 20;   //按键值还原
if((P3 & 0xf0) != 0xf0)   //按键值按下
{
  delay_uint(50);  //按键消抖
  if(((P3 & 0xf0) != 0xf0) && (key_new == 1))
  {    //确认按键按下
   key_new = 0;//标志位清0
   switch(P3 & 0xf0)
   {
    case 0xe0:  key_can = 1;  break;  //左边第1个
    case 0xd0:  key_can = 2;  break;  //左边第2个
    case 0xb0:  key_can = 3;  break;  //左边第3个
    case 0x70:  key_can = 4;  break;  //左边第4个
   }
//   write_sfm2(2,0,key_can);   
  }
}
else
  key_new = 1;
}

/***********读数模转换数据********************************************************/
//请先了解ADC0832模数转换的串行协议,再来读本函数,主要是对应时序图来理解,本函数是模拟0832的串行协议进行的
      //  1  0  0 通道
      //  1  1  1 通道
unsigned char ad0832read(bit SGL,bit ODD)
{
unsigned char i=0,value=0,value1=0;  
  SCL=0;
  DO=1;
  CS=0;  //开始
  SCL=1;  //第一个上升沿
  SCL=0;
  DO=SGL;
  SCL=1;   //第二个上升沿
  SCL=0;
  DO=ODD;
  SCL=1;    //第三个上升沿
  SCL=0;    //第三个下降沿
  DO=1;
  for(i=0;i<8;i++)
  {
   SCL=1;
   SCL=0; //开始从第四个下降沿接收数据
   value<<=1;
   if(DO)
    value++;      
  }
  for(i=0;i<8;i++)
  {   //接收校验数据
   value1>>=1;
   if(DO)
    value1+=0x80;
   SCL=1;
   SCL=0;
  }
  CS=1;
  SCL=1;
  if(value==value1)    //与校验数据比较,正确就返回数据,否则返回0
   return value;
return 0;
}
/*********************小延时函数*****************************/
void delay()
{
_nop_();              //执行一条_nop_()指令就是1us
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();  
}
/*********************超声波测距程序*****************************/
void send_wave()
{
c_send = 1;             //10us的高电平触发
delay();
c_send = 0;  
TH0 = 0;            //给定时器0清零
TL0 = 0;
TR0 = 0;      //关定时器0定时
flag_hc_value = 0;
while(!c_recive);    //当c_recive为零时等待
TR0=1;
while(c_recive)        //当c_recive为1计数并等待
{
  flag_time0 = TH0 * 256 + TL0;
  if((flag_hc_value > 1) || (flag_time0 > 65000))      //当超声波超过测量范围时,显示3个888
  {
   TR0 = 0;
   flag_csb_juli = 2;
   distance = 888;
   flag_hc_value = 0;
   return ;
  }
  else
  {
   flag_csb_juli = 1;   
  }  
}
if(flag_csb_juli == 1)
{
  TR0=0;        //关定时器0定时
  distance = TH0;          //读出定时器0的时间
  distance = distance * 256 + TL0;
  distance +=( flag_hc_value * 65536);//算出超声波测距的时间  得到单位是ms
  distance *= 0.017;               // 0.017 = 340M / 2 = 170M = 0.017M 算出来是米
  if(distance > 350)     //距离 = 速度 * 时间
  {
   distance = 888;     //如果大于3.5m就超出超声波的量程
  }
}  
}
/*********************定时器0、定时器1初始化******************/
void time_init()   
{
EA  = 1;     //开总中断
TMOD = 0X11;   //定时器0、定时器1工作方式1
ET0 = 1;    //开定时器0中断
TR0 = 1;    //允许定时器0定时
ET1 = 1;    //开定时器1中断
TR1 = 1;    //允许定时器1定时
}
/*******************按键执行函数******************/
void key_with()
{
if(menu_1 == 0)
{
  if(key_can == 1)
  {
      miao = 0;fen=45;
   xuexi_start = 1;  //开始学习   
  }
  if(key_can == 2)
  {
   xuexi_start = 0;  //暂停学习
   beep = 1;
  }
  if(key_can == 3)
  {
      xuexi_start = 1;  //继续学习
  }
}
if(key_can == 4)
{
  menu_1 ++;
  if(menu_1 == 1)
  {
   write_string(1,0,"1.xsb:    m     ");
   write_string(2,0,"2.gm:  %        ");
   write_sfm_csb(1,6,set_d);//设置距离参数
   write_sfm2(2,5,set_gx);  //设置光线的参数
   write_com(0x80+0);              //将光标移动到秒个位
   write_com(0x0f);                //显示光标并且闪烁
  }
  if(menu_1 == 2)
  {
   write_com(0x80+0x40+0);              //将光标移动到秒个位
   write_com(0x0f);                //显示光标并且闪烁  
  }
  if(menu_1 >= 3)
  {
   menu_1 = 0;
   write_string(1,0,"csb:    m gm:  %");
   write_string(2,0,"   Time   :      ");
   write_com(0x0c);     //关闭显示
  }   
}
if(menu_1 == 1)   //设置超声波参数
{
  if(key_can == 3)  //
  {
    set_d ++;       //加超声波距离报警数据
   write_sfm_csb(1,6,set_d);
   if(set_d >= 100)
    set_d = 100;
   write_com(0x80);              //将光标移动到秒个位
   write_com(0x0f);                //显示光标并且闪烁  
  }
  if(key_can == 2)  //
  {
    set_d --;       //减超声波距离报警数据
   if(set_d <= 10)
    set_d = 10;
   write_sfm_csb(1,6,set_d);
   write_com(0x80);              //将光标移动到秒个位
   write_com(0x0f);                //显示光标并且闪烁  
  }
  write_eepom_12();     //保存数据
}
if(menu_1 == 2)
{
  if(key_can == 3)  //
  {
    set_gx ++;       //加光线报警数据
   write_sfm2(2,5,set_gx);
   if(set_gx >= 100)
    set_gx = 100;
   write_com(0x80+0x40);              //将光标移动到秒个位
   write_com(0x0f);                //显示光标并且闪烁  
  }
  if(key_can == 2)  //
  {
    set_gx --;       //减光线报警数据
   if(set_gx <= 1)
    set_gx = 1;
   write_sfm2(2,5,set_gx);
   write_com(0x80 + 0x40);              //将光标移动到秒个位
   write_com(0x0f);                //显示光标并且闪烁  
  }
  write_eepom_12();     //保存数据
}
key_can = 20;
}
/*********************报警函数***************************/
void clock_beep()
{
static uchar value1,value2,value3;
// static uint time_value;

if(xuexi_start == 1)
{ if(set_gx >= guangxian)   //距离光线报警
{
  value2 ++;
  if(value2 >= 2)    //循环2次都是报警  增强抗干扰
  {
   flag_alarm = 2;
  }  
}else
  value2 = 0;
  if(distance <= set_d)   //距离报警
  {
   value1 ++;
   if(value1 >= 2)    //循环2次都是报警  增强抗干扰
   {
    flag_alarm = 1;
   }  
  }else
   value1 = 0;     
  if((miao == 0) && (fen == 0))   //时间报警
  {
      xuexi_start = 0;  //休息时间到了,停止学习
   flag_alarm = 3;
  }

}  
if(flag_alarm != 0)
{
  value3 ++;
  beep = ~beep; //报警
  if(value3 > 6)
  {
   value3 = 0;
   beep = 1; //取消报警
   flag_alarm = 0;  
  }   
}     
}
/********************************************************************
* 名称 : Main()
* 功能 : 主函数
* 输入 : 无
* 输出 : 无
***********************************************************************/
void Main()
{
init_1602();   //液晶初始化
time_init();   //定时器初始化
init_eepom();  //EEPROM初始化
// beep = 0;
write_string(1,0,"csb:    m gm:  %");  //让第一行第0个字符显示csb
write_string(2,0,"   Time   :      ");
while(1)
{
  key();      //按键识别函数
  if(key_can < 10)
   key_with();    //按键处理函数
  if(flag_300ms == 1)
  {   
   flag_300ms = 0;
   clock_beep();          //报警函数
   if(menu_1 == 0)
   {
    send_wave();   //超声波测距离
    write_sfm_csb(1,4,distance);
    guangxian = ad0832read(1,0); //采集光线
    guangxian = guangxian * 100 / 255;
    write_sfm2(1,13,guangxian);  //值越大光线就越强

//    write_sfm2(2,3,shi);  //显示时钟
    write_sfm2(2,8,fen);  //显示分钟
    write_sfm2(2,11,miao);  //值越秒钟
   }
  }
}
}

/*********************定时器0中断服务程序 用做超声波测距的************************/
void time0_int() interrupt 1  
{         
flag_hc_value ++;   // TH0 TL0 到65536后溢出中断
}
/*********************定时器1中断服务程序************************/
void time1_int() interrupt 3
{
static uint value;    //定时10ms中断一次
TH1 = 0x3c;
TL1 = 0xb0;     //50ms初值
value++;
if(value % 6 == 0)
{
  flag_300ms = 1;   
}
if(value >= 20)
{
  value = 0 ;
  if(xuexi_start == 1)
  {
   miao--;    //减1秒钟
   if(miao <= -1)
   {
    miao = 59;
    fen --;    //减1分钟
    if(fen < -1)
    {
     fen = 0;
   
    }
   }
  }
}
}

回复

使用道具 举报

ID:631459 发表于 2019-10-28 15:43 | 显示全部楼层
#include "eepom52.h"这个头文件是什么啊,在哪里找
回复

使用道具 举报

ID:155507 发表于 2019-10-29 23:47 | 显示全部楼层
应该是控制 eeprom的头文件

  1. //eepom52.h
  2. #ifndef _EEPOM52_H_
  3. #define _EEPOM52_H_
  4. #include <intrins.h>
  5. #define uchar unsigned char
  6. #define uint unsigned int

  7. /********AT89C51扇区分布*******
  8. 第一扇区:1000H--11FF
  9. 第二扇区:1200H--13FF
  10. 第三扇区:1400H--15FF
  11. 第四扇区:1600H--17FF
  12. 第五扇区:1800H--19FF
  13. 第六扇区:1A00H--1BFF
  14. 第七扇区:1C00H--1DFF
  15. 第八扇区:1E00H--1FFF
  16. *****************/

  17. /********AT89C52扇区分布*******
  18. 第一扇区:2000H--21FF
  19. 第二扇区:2200H--23FF
  20. 第三扇区:2400H--25FF
  21. 第四扇区:2600H--27FF
  22. 第五扇区:2800H--29FF
  23. 第六扇区:2A00H--2BFF
  24. 第七扇区:2C00H--2DFF
  25. 第八扇区:2E00H--2FFF
  26. *****************/


  27. #define RdCommand 0x01 //定义ISP的操作命令
  28. #define PrgCommand 0x02
  29. #define EraseCommand 0x03
  30. #define Error 1
  31. #define Ok 0
  32. #define WaitTime 0x01 //定义CPU的等待时间
  33. sfr ISP_DATA=0xe2;  //寄存器申明
  34. sfr ISP_ADDRH=0xe3;
  35. sfr ISP_ADDRL=0xe4;
  36. sfr ISP_CMD=0xe5;
  37. sfr ISP_TRIG=0xe6;
  38. sfr ISP_CONTR=0xe7;

  39. /* ================ 打开 ISP,IAP 功能 ================= */
  40. void ISP_IAP_enable(void)
  41. {

  42.          EA = 0;       /* 关中断   */
  43.          ISP_CONTR = ISP_CONTR & 0x18;       /* 0001,1000 */
  44.          ISP_CONTR = ISP_CONTR | WaitTime;    /* 写入硬件延时 */
  45.          ISP_CONTR = ISP_CONTR | 0x80;        /* ISPEN=1  */

  46. }
  47. /* =============== 关闭 ISP,IAP 功能 ================== */
  48. void ISP_IAP_disable(void)
  49. {

  50.          ISP_CONTR = ISP_CONTR & 0x7f; /* ISPEN = 0 */
  51.          ISP_TRIG = 0x00;
  52.          EA   =   1;   /* 开中断 */

  53. }
  54. /* ================ 公用的触发代码 ==================== */
  55. void ISPgoon(void)
  56. {

  57.          ISP_IAP_enable();   /* 打开 ISP,IAP 功能 */
  58.          ISP_TRIG = 0x46;    /* 触发ISP_IAP命令字节1 */
  59.          ISP_TRIG = 0xb9;    /* 触发ISP_IAP命令字节2 */
  60.          _nop_();

  61. }
  62. /* ==================== 字节读 ======================== */
  63. unsigned char byte_read(unsigned int byte_addr)
  64. {

  65.         EA = 0;
  66.          ISP_ADDRH = (unsigned char)(byte_addr >> 8);/* 地址赋值 */
  67.          ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff);
  68.          ISP_CMD   = ISP_CMD & 0xf8;   /* 清除低3位  */
  69.          ISP_CMD   = ISP_CMD | RdCommand; /* 写入读命令 */
  70.          ISPgoon();       /* 触发执行  */
  71.          ISP_IAP_disable();    /* 关闭ISP,IAP功能 */
  72.          EA  = 1;
  73.          return (ISP_DATA);    /* 返回读到的数据 */

  74. }
  75. /* ================== 扇区擦除 ======================== */
  76. void SectorErase(unsigned int sector_addr)
  77. {

  78.          unsigned int iSectorAddr;
  79.          iSectorAddr = (sector_addr & 0xfe00); /* 取扇区地址 */
  80.          ISP_ADDRH = (unsigned char)(iSectorAddr >> 8);
  81.          ISP_ADDRL = 0x00;
  82.          ISP_CMD = ISP_CMD & 0xf8;   /* 清空低3位  */
  83.          ISP_CMD = ISP_CMD | EraseCommand; /* 擦除命令3  */
  84.          ISPgoon();       /* 触发执行  */
  85.          ISP_IAP_disable();    /* 关闭ISP,IAP功能 */

  86. }
  87. /* ==================== 字节写 ======================== */
  88. void byte_write(unsigned int byte_addr, unsigned char original_data)
  89. {

  90.          EA  = 0;
  91. //         SectorErase(byte_addr);
  92.          ISP_ADDRH = (unsigned char)(byte_addr >> 8);  /* 取地址  */
  93.          ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff);
  94.          ISP_CMD  = ISP_CMD & 0xf8;    /* 清低3位 */
  95.          ISP_CMD  = ISP_CMD | PrgCommand;  /* 写命令2 */
  96.          ISP_DATA = original_data;   /* 写入数据准备 */
  97.          ISPgoon();       /* 触发执行  */
  98.          ISP_IAP_disable();     /* 关闭IAP功能 */
  99.          EA =1;

  100. }


  101. #endif       

复制代码
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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