找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2734|回复: 4
收起左侧

STC89C52RC单片机控制两块PCF8591进行七路模拟量采集,程序调试不显示。

[复制链接]
ID:496131 发表于 2019-4-19 12:20 | 显示全部楼层 |阅读模式
  1. #include<reg52.h>
  2. #include<stdio.h>
  3. #include <intrins.h>
  4. #include "PCF8591.H"

  5. #define uchar unsigned char
  6. #define uint  unsigned int

  7. #define  PCF8591 0x90    //写数据地址,PCF8591 地址 ,把PCF8591定义成0x90
  8. //第二PCF8591程序
  9. #define  AddWr 0x92    //PCF8591 地址
  10. #define Data  P0    //数据端口
  11. bit ack;                 /*应答标志位*/
  12. sbit RS = P3^0;//Pin4
  13. sbit RW = P3^1; //Pin5
  14. sbit E  = P3^2;//Pin6
  15. unsigned char TempData[8];
  16. unsigned char  FirstLine[16]="Voltage:        ";
  17. unsigned char  SecondLine[16] ="Current:        ";
  18. unsigned char AD_CHANNEL1; // 定义函数中间变量
  19. unsigned char ADtemp;    //定义中间变量
  20. bit P2CF8591_SendByte(unsigned char addr,unsigned char channel);
  21. unsigned char P2CF8591_RcvByte(unsigned char addr);
  22. void disp(void);
  23. void InitLcd();
  24. void mDelay();
  25. sbit scl=P1^1;       //I2C  时钟
  26. sbit sda=P1^0;       //I2C  数据

  27. sbit ENTER = P3^3;        //手动与自动切换
  28. sbit UP = P3^4;                //上
  29. sbit DOWN = P3^5;        //下
  30. sbit LEFT = P3^6;        //左
  31. sbit RIGHT = P3^7;        //右

  32. sbit LED1 = P1^2;
  33. sbit LED2 = P1^3;
  34. uchar Motor_Up[4]={0x08,0x04,0x02,0x01};
  35. uchar Motor_Down[4]={0x01,0x02,0x04,0x08};


  36. uchar Motor_Left[4]={0x10,0x20,0x40,0x80};
  37. uchar Motor_Right[4]={0x80,0x40,0x20,0x10};

  38. unsigned char AD_CHANNEL;  //定义中间变量
  39. //延时函数
  40. void Delay_ms(uint jj)
  41. {
  42.         uint ii;
  43.         while(jj--)
  44.                 for(ii=0;ii<125;ii++);
  45. }
  46. void UART_Init(void)
  47. {
  48.      TMOD = 0x20;   //定时器模式选择
  49.      PCON = 0x00;
  50.      SCON = 0x50;                        
  51.      TH1 = 0xFd;    //设置波特率 9600
  52.      TL1 = 0xFd;
  53.      TR1 = 1;                //启动定时器1
  54.          ES = 1;                //开串口中断
  55.          EA = 1;                //开总中断               
  56. }
  57. /********************************************************************
  58. * 名称   : PSend_Hex()
  59. * 功能   : 发送字符串函数,可控制发送长度
  60. * 变量   : 无
  61. * 返回值 : 无
  62. ********************************************************************/
  63. void Send_Hex(unsigned char *p,unsigned char num)
  64. {
  65.            while(num--)   //剩余发送的字符数
  66.         {
  67.         SBUF = *p; //将要发送的数据赋给串口缓冲寄存器
  68.                 while(!TI);//等待发送结束
  69.                 TI = 0;    //软件清零
  70.                 p++;       //指针加一
  71.         }        
  72. }
  73. void main()           //函数功能:主函数
  74. {         
  75. //        unsigned char ADtemp;                //定义中间变量

  76.         uchar AD_Up,AD_Down,AD_Left,AD_Right;
  77.         uchar i,j,k;
  78.         uchar Table[6];
  79.         Delay_ms(2000);
  80.         UART_Init();        //定时中断函数

  81.         InitLcd();                   //1602初始化
  82.         while(1)
  83.         {
  84.             disp();
  85.                 if(!ENTER)         //手动与自动切换
  86.                 {
  87.                         Delay_ms(20);
  88.                         while(!ENTER);
  89.                         k++;        
  90.                 }
  91.                 if(k%2 == 0) //如果按键被按下
  92.                 {
  93.                 LED1 = 1;
  94.                 LED2 = 0;
  95.                 for(i=0;i<8;i++)
  96.                 {
  97.                         switch(AD_CHANNEL)
  98.                         {
  99.                                 case 0: PCF8591_ISendByte(PCF8591,0x41);
  100.                                 AD_Up=PCF8591_IRcvByte(PCF8591)*2;  //ADC0 模数转换1
  101.                                 break;  
  102.                                 
  103.                                 case 1: PCF8591_ISendByte(PCF8591,0x42);
  104.                                 AD_Down=PCF8591_IRcvByte(PCF8591)*2;  //ADC1  模数转换2
  105.                                 break;  
  106.                                 case 2: PCF8591_ISendByte(PCF8591,0x43);
  107.                                 AD_Left=PCF8591_IRcvByte(PCF8591)*2;  //ADC2 模数转换3
  108.                                 break;  
  109.                                 
  110.                                 case 3: PCF8591_ISendByte(PCF8591,0x40);
  111.                                 AD_Right=PCF8591_IRcvByte(PCF8591)*2;  //ADC3  模数转换4
  112.                                 break;
  113.                         }

  114.                         Send_Hex(Table,4);
  115.                         if(++AD_CHANNEL>3)
  116.                         {
  117.                          AD_CHANNEL=0;
  118.                         Table[0] = AD_Up;
  119.                         Table[1] = AD_Down;
  120.                         Table[2] = AD_Left;
  121.                         Table[3] = AD_Right;
  122.                          }

  123.                 }        
  124.                 }
  125.                 if(AD_CHANNEL1=0)          //第二PCF8591程序
  126.                 {
  127.                         P2CF8591_SendByte(AddWr,1);
  128.                         ADtemp = P2CF8591_RcvByte(AddWr);  //ADC0 模数转换1        
  129.                         TempData[0]=(ADtemp*10/51)/10;             //处理0通道电压显示
  130.                         TempData[1]=(ADtemp*10/51)%100;             //处理0通道电压显示
  131.                         TempData[2]=((ADtemp*10)%51)/5;
  132.                         TempData[3]=((ADtemp*10)%51)%5;
  133.                 }                                                                    
  134.                 else //(AD_CHANNEL1=1)
  135.                 {        
  136.                         P2CF8591_SendByte(AddWr,0);
  137.                         ADtemp=P2CF8591_RcvByte(AddWr);  //ADC1  模数转换2
  138.                         TempData[4]=ADtemp/51;//处理1通道电压显示
  139.                           TempData[6]=(ADtemp%51)/5;         
  140.                 }                        
  141.            if(++AD_CHANNEL1>2) AD_CHANNEL1=0;
  142.            disp();         
  143.            
  144.                 if(k%2 == 1)        //如果按键没有被按下
  145.                 {
  146.                         LED1 = 0;
  147.                         LED2 = 1;
  148.                         AD_Up = 0;        //上
  149.                         AD_Down = 0;//下
  150.                         AD_Left = 0;//左
  151.                         AD_Right = 0;//右        
  152.                 }               
  153.         ///////根据光敏电阻A/D采样结果,进行两两比较//////////
  154.          
  155.                 if(((AD_Up<AD_Down)&&(AD_Down-AD_Up>10))||(!UP))//上转
  156.                 {
  157.                         for(i=0;i<10;i++)
  158.                         {
  159.                                 for(j=0;j<4;j++)
  160.                                 {
  161.                                         P2=Motor_Up[j];
  162.                                         Delay_ms(10);
  163.                                 }               
  164.                         }        
  165.                 }
  166.                 //////////////////上下光敏电阻A/D值比较////////////////////
  167.                 if(((AD_Up>AD_Down)&&(AD_Up-AD_Down>10))||(!DOWN))//下转
  168.                 {
  169.                         for(i=0;i<10;i++)
  170.                         {
  171.                                 for(j=0;j<4;j++)
  172.                                 {
  173.                                         P2=Motor_Down[j];
  174.                                         Delay_ms(10);
  175.                                 }               
  176.                         }
  177.                 }
  178.                 //////////////左右光敏电阻A/D值比较///////////////
  179.                 if(((AD_Left<AD_Right)&&(AD_Right-AD_Left>10))||(!LEFT))//左转
  180.                 {
  181.                         for(i=0;i<10;i++)
  182.                         {
  183.                                 for(j=0;j<4;j++)
  184.                                 {
  185.                                         P2=Motor_Left[j];
  186.                                         Delay_ms(10);
  187.                                 }               
  188.                         }
  189.                
  190.                 }
  191.                 ////////////////////左右光敏电阻A/D值比较//////////////////
  192.                 if(((AD_Left>AD_Right)&&(AD_Left-AD_Right>10))||(!RIGHT))//右转
  193.                 {
  194.                         for(i=0;i<10;i++)
  195.                         {
  196.                                 for(j=0;j<4;j++)
  197.                                 {
  198.                                         P2=Motor_Right[j];
  199.                                         Delay_ms(10);
  200.                                 }               
  201.                         }
  202.                 }
  203.                 ////////////////////////////////////
  204.                 Delay_ms(100);//延时,可适当修改
  205.         }
  206. /*        switch(AD_CHANNEL1)          //第二PCF8591程序
  207.                 {
  208.                         case 0: P2CF8591_SendByte(AddWr,1);
  209.                              ADtemp = P2CF8591_RcvByte(AddWr);  //ADC0 模数转换1        
  210.                                  TempData[0]=(ADtemp*10/51)/10;             //处理0通道电压显示
  211.                                  TempData[1]=(ADtemp*10/51)%100;             //处理0通道电压显示
  212.                                  TempData[2]=((ADtemp*10)%51)/5;
  213.                                  TempData[3]=((ADtemp*10)%51)%5;
  214.                                                                                    
  215.                                  break;  
  216.                         
  217.                         case 1: P2CF8591_SendByte(AddWr,0);
  218.                              ADtemp=P2CF8591_RcvByte(AddWr);  //ADC1  模数转换2
  219.                                  TempData[4]=ADtemp/51;//处理1通道电压显示
  220.                                    TempData[6]=(ADtemp%51)/5;
  221.                                  break;  
  222.                         
  223.                         
  224.                 }                        
  225.            if(++AD_CHANNEL1>2) AD_CHANNEL1=0;
  226.            disp();          */
  227. }

  228. //第二个模块程序

  229. /*******************************************************************
  230.                      起动总线函数               
  231. 函数原型: void  Start_I2c();  
  232. 功能:     启动I2C总线,即发送I2C起始条件.  
  233. ********************************************************************/
  234. void Start_I2c()
  235. {
  236.   sda=1;         /*发送起始条件的数据信号*/
  237.   _nop_();
  238.   scl=1;
  239.   _nop_();        /*起始条件建立时间大于4.7us,延时*/
  240.   _nop_();
  241.   _nop_();
  242.   _nop_();
  243.   _nop_();   
  244.   sda=0;         /*发送起始信号*/
  245.   _nop_();        /* 起始条件锁定时间大于4μs*/
  246.   _nop_();
  247.   _nop_();
  248.   _nop_();
  249.   _nop_();      
  250.   scl=0;       /*钳住I2C总线,准备发送或接收数据 */
  251.   _nop_();
  252.   _nop_();
  253. }

  254. /*******************************************************************
  255.                       结束总线函数               
  256. 函数原型: void  Stop_I2c();  
  257. 功能:     结束I2C总线,即发送I2C结束条件.  
  258. ********************************************************************/
  259. void Stop_I2c()
  260. {
  261.   sda=0;      /*发送结束条件的数据信号*/
  262.   _nop_();       /*发送结束条件的时钟信号*/
  263.   scl=1;      /*结束条件建立时间大于4μs*/
  264.   _nop_();
  265.   _nop_();
  266.   _nop_();
  267.   _nop_();
  268.   _nop_();
  269.   sda=1;      /*发送I2C总线结束信号*/
  270.   _nop_();
  271.   _nop_();
  272.   _nop_();
  273.   _nop_();
  274. }

  275. /*******************************************************************
  276.                  字节数据发送函数               
  277. 函数原型: void  I2C_SendByte(UCHAR c);
  278. 功能:     将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
  279.           此状态位进行操作.(不应答或非应答都使ack=0)     
  280.            发送数据正常,ack=1; ack=0表示被控器无应答或损坏。
  281. ********************************************************************/
  282. void  I2C_SendByte(unsigned char  c)
  283. {
  284. unsigned char  i;

  285. for(i=0;i<8;i++)  /*要传送的数据长度为8位*/
  286.     {
  287.      if((c<<i)&0x80)sda=1;   /*判断发送位*/
  288.        else  sda=0;               
  289.      _nop_();
  290.      scl=1;               /*置时钟线为高,通知被控器开始接收数据位*/
  291.       _nop_();
  292.       _nop_();             /*保证时钟高电平周期大于4μs*/
  293.       _nop_();
  294.       _nop_();
  295.       _nop_();         
  296.      scl=0;
  297.     }

  298.     _nop_();
  299.     _nop_();
  300.     sda=1;                /*8位发送完后释放数据线,准备接收应答位*/
  301.     _nop_();
  302.     _nop_();   
  303.     scl=1;
  304.     _nop_();
  305.     _nop_();
  306.     _nop_();
  307.     if(sda==1)ack=0;     
  308.        else ack=1;        /*判断是否接收到应答信号*/
  309.     scl=0;
  310.     _nop_();
  311.     _nop_();
  312. }

  313. /*******************************************************************
  314.                  字节数据接收函数               
  315. 函数原型: UCHAR  I2C_RcvByte();
  316. 功能:        用来接收从器件传来的数据,并判断总线错误(不发应答信号),
  317.           发完后请用应答函数应答从机。  
  318. ********************************************************************/   
  319. unsigned char   I2C_RcvByte()
  320. {
  321.   unsigned char  retc=0,i;
  322.   sda=1;                     /*置数据线为输入方式*/
  323.   for(i=0;i<8;i++)
  324.       {
  325.         _nop_();           
  326.         scl=0;                  /*置时钟线为低,准备接收数据位*/
  327.         _nop_();
  328.         _nop_();                 /*时钟低电平周期大于4.7μs*/
  329.         _nop_();
  330.         _nop_();
  331.         _nop_();
  332.         scl=1;                  /*置时钟线为高使数据线上数据有效*/
  333.         _nop_();
  334.         _nop_();
  335.         retc=retc<<1;
  336.         if(sda==1)retc=retc+1;  /*读数据位,接收的数据位放入retc中 */
  337.         _nop_();
  338.         _nop_();
  339.       }
  340.   scl=0;   
  341.   _nop_();
  342.   _nop_();
  343.   return(retc);
  344. }

  345. /********************************************************************
  346.                      应答子函数
  347. 函数原型:  void Ack_I2c(bit a);
  348. 功能:      主控器进行应答信号(可以是应答或非应答信号,由位参数a决定)
  349. ********************************************************************/
  350. void Ack_I2c(bit a)
  351. {  
  352.   if(a==0)
  353.   {
  354.   sda=0;
  355.     _nop_();
  356.   _nop_();
  357.   _nop_();      
  358.   scl=1;
  359.   _nop_();
  360.   _nop_();                    /*时钟低电平周期大于4μs*/
  361.   _nop_();
  362.   _nop_();
  363.   _nop_();  
  364.   scl=0;                     /*清时钟线,住I2C总线以便继续接收*/
  365.   _nop_();
  366.   _nop_();   
  367.   sda=1;
  368.     _nop_();
  369.   _nop_();   

  370.   }              /*在此发出应答或非应答信号 */
  371.   else
  372. {  sda=1;                                  /*0为发出应答,1为非应答信号 */
  373.   _nop_();
  374.   _nop_();
  375.   _nop_();      
  376.   scl=1;
  377.   _nop_();
  378.   _nop_();                    /*时钟低电平周期大于4μs*/
  379.   _nop_();
  380.   _nop_();
  381.   _nop_();  
  382.   scl=0;                     /*清时钟线,住I2C总线以便继续接收*/
  383.   _nop_();
  384.   _nop_();
  385.   sda=0;
  386.       _nop_();
  387.   _nop_();   

  388.   }   
  389. }

  390. /************************************************************
  391. * 函数名        : Pcf8591_SendByte
  392. * 函数功能                : 写入一个控制命令
  393. * 输入          : addr(器件地址),channel(转换通道)
  394. * 输出                 : 无
  395. ************************************************************/
  396. bit P2CF8591_SendByte(unsigned char addr,unsigned char channel)
  397. {
  398.    Start_I2c();              //启动总线
  399.    I2C_SendByte(addr);            //发送器件地址
  400.    if(ack==0)return(0);
  401.    I2C_SendByte(0x40|channel);              //发送控制字节
  402.    if(ack==0)return(0);
  403.    Stop_I2c();               //结束总线
  404.    return(1);
  405. }

  406. /************************************************************
  407. * 函数名               : PCF8591_RcvByte
  408. * 函数功能           : 读取一个转换值
  409. * 输入          :
  410. * 输出          : dat
  411. ************************************************************/
  412. unsigned char P2CF8591_RcvByte(unsigned char addr)
  413. {  
  414.    unsigned char dat;

  415.    Start_I2c();          //启动总线
  416.    I2C_SendByte(addr+1);      //发送器件地址
  417.    if(ack==0)return(0);
  418.    dat=I2C_RcvByte();          //读取数据0

  419.    Ack_I2c(1);           //发送非应答信号
  420.    Stop_I2c();           //结束总线
  421.    return(dat);
  422. }

  423. /******************************************************************/
  424. /*                   1602液晶屏相关函数                           */
  425. /******************************************************************/
  426. void DelayUs(unsigned char us)//delay us
  427. {
  428. unsigned char uscnt;
  429. uscnt=us>>1;/* Crystal frequency in 12MHz*/
  430. while(--uscnt);
  431. }
  432. /******************************************************************/
  433. void DelayMs(unsigned char ms)//delay Ms
  434. {
  435. while(--ms)
  436.    {
  437.      DelayUs(250);
  438.      DelayUs(250);
  439.          DelayUs(250);
  440.          DelayUs(250);
  441.    }
  442. }
  443. void WriteCommand(unsigned char c)
  444. {
  445.         DelayMs(5);//short delay before operation
  446.         E=0;
  447.         RS=0;
  448.         RW=0;
  449.         _nop_();
  450.         E=1;
  451.         Data=c;
  452.         E=0;
  453. }
  454. /****************************************************************/
  455. void WriteData(unsigned char c)
  456. {
  457. DelayMs(5);   //short delay before operation
  458. E=0;
  459. RS=1;
  460. RW=0;
  461. _nop_();
  462. E=1;
  463. Data=c;
  464. E=0;
  465. RS=0;
  466. }
  467. /*********************************************************************/
  468. void ShowChar(unsigned char pos,unsigned char c)
  469. {
  470. unsigned char p;
  471. if (pos>=0x10)
  472.     p=pos+0xb0; //是第二行则命令代码高4位为0xc
  473. else
  474.     p=pos+0x80; //是第二行则命令代码高4位为0x8
  475. WriteCommand (p);//write command
  476. WriteData (c);   //write data
  477. }
  478. /*************************************************************************/
  479. void ShowString (unsigned char line,char *ptr)
  480. {
  481. unsigned char l,i;
  482. l=line<<4;
  483. for (i=0;i<16;i++)
  484.   ShowChar (l++,*(ptr+i));//循环显示16个字符
  485. }
  486. /*********************************************************************/
  487. void InitLcd()
  488. {
  489. DelayMs(15);
  490. WriteCommand(0x38); //display mode
  491. WriteCommand(0x38); //display mode
  492. WriteCommand(0x38); //display mode
  493. WriteCommand(0x06); //显示光标移动位置
  494. WriteCommand(0x0c); //显示开及光标设置
  495. WriteCommand(0x01); //显示清屏

  496. }

  497. void disp(void)
  498. {
  499.    unsigned char i=0;
  500.    while(FirstLine[i]!=' ')
  501.    {
  502.            ShowString(0,FirstLine);
  503.         i++;
  504.    }
  505.         FirstLine[8]= '0'+TempData[0];
  506.         FirstLine[9]= '0'+TempData[1];
  507.         FirstLine[10]='.';
  508.         FirstLine[11]='0'+TempData[2];
  509.         FirstLine[12]='0'+TempData[3];
  510.         FirstLine[14]='V';
  511.                
  512.         ShowString(0,FirstLine);
  513.         
  514.         while(SecondLine[i]!=' ')
  515.         {
  516.                    ShowString(1,SecondLine);
  517.                 i++;
  518.         }
  519.         SecondLine[8]='0'+TempData[4];
  520.         SecondLine[11]='0'+TempData[6];
  521.         SecondLine[10]='.';
  522.         SecondLine[14]='V';
  523.         
  524.         ShowString(1,SecondLine);
  525. }
  526. /*------------------------------------------------
  527.                     延时程序
  528. ------------------------------------------------*/
  529. void mDelay(unsigned char j)
  530. {
  531.   unsigned int i;
  532.   for(;j>0;j--)
  533.      {
  534.           for(i=0;i<125;i++)
  535.              {;}
  536.           }
  537.   }
复制代码

程序修改.rar

124.98 KB, 下载次数: 37

仿真

回复

使用道具 举报

ID:496131 发表于 2019-4-19 22:11 | 显示全部楼层
自己修改成功啦,谢谢各位高手
回复

使用道具 举报

ID:465737 发表于 2020-1-30 14:28 | 显示全部楼层
请问一下,您这个是怎样解决问题的呢,我遇到了差不多的问题,单片机不工作
回复

使用道具 举报

ID:648281 发表于 2020-1-30 19:29 | 显示全部楼层
ljw8005 发表于 2020-1-30 14:28
请问一下,您这个是怎样解决问题的呢,我遇到了差不多的问题,单片机不工作

你好!
具体是什么现象呢?拍照或截图说明情况
回复

使用道具 举报

ID:1084659 发表于 2023-7-24 18:23 | 显示全部楼层
你好想问一下怎么解决的
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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