找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2489|回复: 25
收起左侧

同时使用单片机外部中断0,1与定时器中断0,1的程序问题

[复制链接]
ID:89072 发表于 2021-12-7 10:05 | 显示全部楼层 |阅读模式
在调试485控制时,用到了外部中断0和外部中断1,使用的别人的Modbus RTU程序,自己又需要使用红外设置,作为按键使用,由于基础不好,现在卡在两个定时器同时使用时,无法Modbus通讯,设置了外部中断1优先级为0,当设置定时器1的工作模式2时
单片机源程序如下:
void timer_init(void)//定时器初始化
{

//    IPH |= 0x01;
//    PT1=1;
//IP = 0x08;
//IPH = 0x08;
        TMOD =0x30;/////////设置工作方式2
        TH1=0x00; //重载值
        TL1=0x00; //初始化值
        EA=1;        
        ET1=1;//开总中断;开定时器中断
        TR1=1;////////启动计数器
}

TMOD=0x20时,Modbus RTU就无法使用,很郁闷,请大神帮我分析下怎样设置,非常感谢。

void TimesMsinitInt(void)
{
    unsigned long tmp = 0;

    TMOD &= ~GATE0;//0000 0000
    TMOD &= ~C_T0;//0000 0000
    TMOD |= T0_M1;//0000 0001                        //模式1,16位

    //$$$. 定时器初值计算
    //tmp=(0xffff-TimeVals*(1000.0/(FOSC/12000)));        //时间计算公式
    //.................................................................
    tmp = 65536UL - FOSC / 12000000.0 * TimeVals;
    TIMER_HIGHT = (uchar)(tmp >> 8);                //初值计算
    TIMER_LOW = (uchar)(tmp & 0xff);
    //
    TH0 = TIMER_HIGHT;                                                //加载初值
    TL0 = TIMER_LOW;



    //$$$. 允许中断,开启定时器
    //.................................................................
    TR0 = 1;                                                                //打开定时器
    ET0 = 1;                                                                //允许定时器中断
}

//这是Modbus的定时器设置
//T1 相关的位定义
#define         GATE1        0x80
#define         C_T1        0x40
#define         T1_M2        0x20
#define         T1_M1        0x10
//T0 相关的位定义
#define         GATE0        0x08
#define         C_T0        0x04
#define         T0_M2        0x02
#define         T0_M1        0x01

这是T1与T0的定义

Modbus.rar

10.25 KB, 下载次数: 9

回复

使用道具 举报

ID:57657 发表于 2021-12-7 10:59 | 显示全部楼层
你用了外部中断0、1,EX0=1; 和 EX1=1;  以及中断入口哪里去了?
回复

使用道具 举报

ID:89072 发表于 2021-12-7 11:11 | 显示全部楼层
npn 发表于 2021-12-7 10:59
你用了外部中断0、1,EX0=1; 和 EX1=1;  以及中断入口哪里去了?

/*************************************
                01 (0x01)        读线圈
        02 (0x02)        读离散量输入
        03 (0x03)        读保持寄存器
        04(0x04)         读输入寄存器
        05 (0x05)        写单个线圈
        06 (0x06)        写单个寄存器
        15 (0x0F)        写多个线圈
        16 (0x10)        写多个寄存器
*************************************/
#define _MAIN_C_
//============================
#include "includeFile.h"
//============================
#include "Delay.h"
sfr P4   = 0xC0; //8 bitPort4

bit irpro_ok,irok;
sbit IR=P3^3;  //红外接口标志
uint count;  
uchar  irtime;
//u8  numa = 234;
sbit LED = P4^4;

uchar IRcord[6];
uchar irdata[33];
uchar code TabA[22]="0123456789ABCDEFGHIJKL";
uchar data TimeNum[]="                      ";

/*------------------------------------------------
                  定时器1中断处理
void tm1_isr() interrupt 1
------------------------------------------------*/
void tim1_isr()interrupt 3  //定时中断
{
        irtime++;

}
/*------------------------------------------------
                  外部中断0中断处理
------------------------------------------------*/
void EX0_ISR (void) interrupt 2  //外部中断1服务函数
{
  static unsigned char   i;             //接收红外信号处理
  static bit startflag;                //是否开始处理标志位
if(startflag)                        
   {

   if(irtime<63&&irtime>=33)//引导码 TC9012的头码,9ms+4.5ms
            i=0;
                    irdata=irtime;//存储每个电平的持续时间,用于以后判断是0还是1
                    irtime=0;
                    i++;
                            if(i==33)
                              {
                                   irok=1;
                                 i=0;
                                  }
          }
           else
                {
                irtime=0;
                startflag=1;

                }

}

/*------------------------------------------------
                定时器0初始化
------------------------------------------------*/
void timer_init(void)//定时器初始化
{

//    IPH |= 0x01;
//    PT1=1;
//IP = 0x08;
//IPH = 0x08;
        TMOD =0x30;/////////设置工作方式2
        TH1=0x00; //重载值
        TL1=0x00; //初始化值
        EA=1;       
        ET1=1;//开总中断;开定时器中断
        TR1=1;////////启动计数器
}

/*------------------------------------------------
                  外部中断1初始化
------------------------------------------------*/
void EX0init(void)
{
//IPH = 0x00;
//PX1 = 1;
IPH = 0x04;
IP = 0x00;
        IT1 = 1;   //指定外部中断1下降沿触发,INT0 (P3.3)
        EX1 = 1;   //使能外部中断
        EA = 1;    //开总中断


}

/*------------------------------------------------
                  键值处理
注:分解显示转换值列表

------------------------------------------------*/
void Ir_work(void)//红外键值散转程序
{
        TimeNum[5] = TabA[IRcord[0]/16];   //处理客户码并显示
        TimeNum[6] = TabA[IRcord[0]%16];
        TimeNum[8] = TabA[IRcord[1]/16];   //处理客户码并显示
        TimeNum[9] = TabA[IRcord[1]%16];
        TimeNum[11] = TabA[IRcord[2]/16];  //处理数据码并显示
        TimeNum[12] = TabA[IRcord[2]%16];
        TimeNum[14] = TabA[IRcord[3]/16];  //处理数据反码并显示
        TimeNum[15] = TabA[IRcord[3]%16];
        TimeNum[17] = TabA[IRcord[4]/16];  //处理数据反码并显示
        TimeNum[18] = TabA[IRcord[4]%16];
        TimeNum[20] = TabA[IRcord[5]/16];  //处理数据反码并显示
        TimeNum[21] = TabA[IRcord[5]%16];
        irpro_ok=0;//处理完成标志
  }

/***************************************************************/
void Ir_towork(void)//红外键值散转程序
{

//            PutStr(1,0,TimeNum);//显示处理过后的码值
           switch(IRcord[2])//判断第三个数码值
         {
                        case 0x0d:OLED_ShowNum(72,6,46,4,16);break;//o
                        case 0x0c:OLED_ShowNum(0,104,RegBuf_HOLD[0],4,16);break;//1 显示相应的按键值
                        case 0x18:OLED_ShowNum(72,6,456,4,16);break;//2
/***********
                        case 0x5e:LCD1602_Dis_OneChar(4,0,Tab[3]);break;//3
                        case 0x08:LCD1602_Dis_OneChar(4,0,Tab[4]);break;//4
                        case 0x1c:LCD1602_Dis_OneChar(4,0,Tab[5]);break;//5
                        case 0x5a:LCD1602_Dis_OneChar(4,0,Tab[6]);break;//6
                        case 0x42:LCD1602_Dis_OneChar(4,0,Tab[7]);break;//7
                        case 0x52:LCD1602_Dis_OneChar(4,0,Tab[8]);break;//8
                        case 0x4a:LCD1602_Dis_OneChar(4,0,Tab[9]);break;//9
                        case 0x45:LCD1602_Dis_OneChar(4,0,Tab[10]);break;//1
                        case 0x46:LCD1602_Dis_OneChar(4,0,Tab[11]);break;//1
                        case 0x47:LCD1602_Dis_OneChar(4,0,Tab[12]);break;//1
                        case 0x44:LCD1602_Dis_OneChar(4,0,Tab[13]);break;//1
                        case 0x40:LCD1602_Dis_OneChar(4,0,Tab[14]);break;//1
                        case 0x43:LCD1602_Dis_OneChar(4,0,Tab[15]);break;//1
                        case 0x07:LCD1602_Dis_OneChar(4,0,Tab[16]);break;//1
                        case 0x15:LCD1602_Dis_OneChar(4,0,Tab[17]);break;//1
                        case 0x09:LCD1602_Dis_OneChar(4,0,Tab[18]);break;//1   
                        case 0x16:LCD1602_Dis_OneChar(4,0,Tab[19]);break;//1
                        case 0x19:LCD1602_Dis_OneChar(4,0,Tab[20]);break;//1             
             default:break;       
**********/
                  
                         }
                         irpro_ok=0;//处理完成标志                                       
}

/********************************************
                红外码值处理
*******************************************/
void Ircordpro(void)//红外码值处理函数
{
  unsigned char  i, j, k;
  unsigned char  cord,value;

  k=1;
  for(i=0;i<4;i++)      //处理4个字节
     {
      for(j=1;j<=8;j++) //处理1个字节8位
         {
          cord=irdata[k];
          if(cord>7)//大于某值为1,这个和晶振有绝对关系,这里使用12M计算,此值可以有一定误差
             value|=0x80;
          if(j<8)
                    {
                         value>>=1;
                        }
           k++;
         }
     IRcord=value;
     value=0;
//         tablex(IRcord[2]);     
     }
         irpro_ok=1;//处理完毕标志位置1
}


/******************************************************************
功能: 初始化
输入:        站号设置
输出: 无
版本: V15.09.0
作者: 大姆指测控 - 姚工,   QQ:657874307
修改日期: 2015-09
说明:,根据P2口低四位编码开关的设置,修改从站地址1-32位,默认都为0则实际地址为1
******************************************************************/
uchar  Get_ID_HD(void)
{
    uchar temp,i=50;

    P2|=0x0f;//0000 1111
    while(i--);

    temp=~P2;                //P2.0-P2.3接拨码开关,用来设置4位站号 1111 0000
    temp&=0x0f;     //1111 0000&0000 1111 temp = 0000 0000

    if(temp==0)
    {
        return 1;        //站号不能为0,返回默认的1
    }
    return temp;        //返回站号
}

/******************************************************************
功能: 初始化
输入:        无
输出: 无
版本: V15.09.0
作者: 大姆指测控 - 姚工,   QQ:657874307
修改日期: 2015-09
说明:系统上电之后,先取得系统设置的参数,然后用这些参数来对相应的模块进行初始化,如下:
                1. 串口通信的波特率 和 校验值 [决定本从机的通信参数];
                2. modbus 从机的站号 ,可以使用拨码开关来设定站号,或者使用EEPROM存储站号;
******************************************************************/
void SYSinit(void)
{
       TimesMsinitInt();                                        //Ms定时器初始化,用作产生1ms的系统时间基准
                OLED_Init();                        //初始化OLED  
                timer_init();//初始化定时器(打开后出现连接不上问题)
                EX0init(); //初始化外部中断

    //先写相应的函数,取得系统参数....
    //以下例程使用固定值:19200 ,无校验,
    //站号 =拨码开关设定1-32
    UartInit(19200, NONE_PARITY);                //串口初始化[须要确定好波特率和校验值]
    ModbusInit(Get_ID_HD(),StartSend);         //Modbus串口初始化[须要确定好站号]
    //
//       IP = 0x03;
//       IPH = 0x09;
    EA = 1;

}


//----------------------------START-------------------------------
//=================================================================
void main(void)
{
               
//                u8 Data_p = P2;
                SYSinit();                                                        //系统初始化

//                numa = 0x01;
                OLED_Clear();
                OLED_ShowCHinese(0,0,0);//
                OLED_ShowCHinese(18,0,1);//
                OLED_ShowCHinese(36,0,2);//
                OLED_ShowCHinese(54,0,3);//
                OLED_ShowCHinese(72,0,4);//
                OLED_ShowCHinese(90,0,5);//
//                OLED_ShowCHinese(108,0,6);//


    while (1)
    {
        UartRxPoll();                                   //串口数据帧检查处理
        TEST1();
        //......
       //继续添加应用程序代码...
         LED=1;

/******************************
功能:读寄存器
调用:RegBuf_Input[0],0为寄存器地址对应30001
*****************************/
                OLED_ShowNum(0,6,RegBuf_Input[0],4,16);
                OLED_ShowNum(32,6,RegBuf_Input[1],4,16);
                OLED_ShowNum(64,6,RegBuf_Input[2],4,16);
                OLED_ShowNum(96,6,RegBuf_Input[3],4,16);

/******************************
功能:读写寄存器
调用:RegBuf_HOLD[0],0为寄存器地址对应40001
*****************************/

                OLED_ShowNum(0,4,RegBuf_HOLD[0],4,16);//最大16950
                OLED_ShowNum(32,4,RegBuf_HOLD[1],4,16);//最大16950
                OLED_ShowNum(64,4,RegBuf_HOLD[2],4,16);//最大16950
                OLED_ShowNum(96,4,RegBuf_HOLD[3],4,16);//最大16950

//                OLED_ShowNum(0,6,SwBuf_IN[0],4,16);//最大16950
//      OLED_ShowChar(40,6,SwBuf_IN[0]);

/***************测试控制*************/
                OLED_ShowChar(0,2,TimeNum[5]);
                OLED_ShowChar(8,2,TimeNum[6]);
                OLED_ShowChar(16,2,TimeNum[8]);
                OLED_ShowChar(24,2,TimeNum[9]);
                OLED_ShowChar(32,2,TimeNum[11]);
                OLED_ShowChar(40,2,TimeNum[12]);
                OLED_ShowChar(48,2,TimeNum[14]);
                OLED_ShowChar(56,2,TimeNum[15]);
                OLED_ShowChar(64,2,TimeNum[17]);
                OLED_ShowChar(72,2,TimeNum[18]);
                OLED_ShowChar(80,2,TimeNum[20]);
                OLED_ShowChar(88,2,TimeNum[21]);
                if(irok)                        //如果接收好了进行红外处理
                  {   
         
                   Ircordpro();
                   irok=0;
                  }

                if(irpro_ok)                   //如果处理好后进行工作处理,如按对应的按键后显示对应的数字等
                  {
                   Ir_work();
                   Ir_towork();
                  }



    }
}



开始以为时红外遥控程序问题,我都放在主程序里面调试了
回复

使用道具 举报

ID:89072 发表于 2021-12-7 11:13 | 显示全部楼层
Modbus 程序与红外程序单独调试都没问题,但是放在一起就会冲突
回复

使用道具 举报

ID:234769 发表于 2021-12-7 11:18 | 显示全部楼层
UART 也用中断
回复

使用道具 举报

ID:636538 发表于 2021-12-7 11:29 | 显示全部楼层
不明白你想做什么,TMOD =0x30;定时器/计数器1停止工作,此时无效,TMOD =0x20,定时器/计数器1八位自动重载计数,你想两个定时器同时使用TMOD=0X20;//定时器1工作在8位自动重载,TMOD |=0X01;//定时器0工作在模式1,16位,Modbus RTU应该是你串口接收停止比如超过10ms,认为接收完毕,进行数据处理,可是你定时器1来给计时的话,你设定时间是多少,没有预设值,
void Timer1Init(void)                //10毫秒@11.0592MHz
{
        AUXR &= 0xBF;                //定时器时钟12T模式
        TMOD &= 0x0F;                //设置定时器模式
        TL1 = 0x00;                //设置定时初始值
        TH1 = 0xDC;                //设置定时初始值
        TF1 = 0;                //清除TF1标志
        TR1 = 1;                //定时器1开始计时
}
回复

使用道具 举报

ID:89072 发表于 2021-12-7 12:30 | 显示全部楼层
SKYLAR123 发表于 2021-12-7 11:29
不明白你想做什么,TMOD =0x30;定时器/计数器1停止工作,此时无效,TMOD =0x20,定时器/计数器1八位自动重 ...
  1. /*************************************
  2.                 01 (0x01)        读线圈
  3.         02 (0x02)        读离散量输入
  4.         03 (0x03)        读保持寄存器
  5.         04(0x04)         读输入寄存器
  6.         05 (0x05)        写单个线圈
  7.         06 (0x06)        写单个寄存器
  8.         15 (0x0F)        写多个线圈
  9.         16 (0x10)        写多个寄存器
  10. *************************************/
  11. #define _MAIN_C_
  12. //============================
  13. #include "includeFile.h"
  14. //============================
  15. #include "Delay.h"
  16. sfr P4   = 0xC0; //8 bitPort4

  17. bit irpro_ok,irok;
  18. sbit IR=P3^3;  //红外接口标志
  19. uint count;  
  20. uchar  irtime;
  21. //u8  numa = 234;
  22. sbit LED = P4^4;

  23. uchar IRcord[6];
  24. uchar irdata[33];
  25. uchar code TabA[22]="0123456789ABCDEFGHIJKL";
  26. uchar data TimeNum[]="                      ";

  27. /*------------------------------------------------
  28.                   定时器1中断处理
  29. void tm1_isr() interrupt 1
  30. ------------------------------------------------*/
  31. void tim1_isr()interrupt 3  //定时中断
  32. {
  33.         irtime++;

  34. }
  35. /*------------------------------------------------
  36.                   外部中断0中断处理
  37. ------------------------------------------------*/
  38. void EX0_ISR (void) interrupt 2  //外部中断1服务函数
  39. {
  40.   static unsigned char   i;             //接收红外信号处理
  41.   static bit startflag;                //是否开始处理标志位
  42. if(startflag)                        
  43.    {

  44.    if(irtime<63&&irtime>=33)//引导码 TC9012的头码,9ms+4.5ms
  45.             i=0;
  46.                     irdata[i]=irtime;//存储每个电平的持续时间,用于以后判断是0还是1
  47.                     irtime=0;
  48.                     i++;
  49.                             if(i==33)
  50.                               {
  51.                                    irok=1;
  52.                                  i=0;
  53.                                   }
  54.           }
  55.            else
  56.                 {
  57.                 irtime=0;
  58.                 startflag=1;

  59.                 }

  60. }

  61. /*------------------------------------------------
  62.                 定时器0初始化
  63. ------------------------------------------------*/
  64. void timer_init(void)//定时器初始化
  65. {

  66. //    IPH |= 0x01;
  67. //    PT1=1;
  68. //IP = 0x08;
  69. //IPH = 0x08;
  70.         TMOD =0x30;/////////设置工作方式2
  71.         TH1=0x00; //重载值
  72.         TL1=0x00; //初始化值
  73.         EA=1;       
  74.         ET1=1;//开总中断;开定时器中断
  75.         TR1=1;////////启动计数器
  76. }

  77. /*------------------------------------------------
  78.                   外部中断1初始化
  79. ------------------------------------------------*/
  80. void EX0init(void)
  81. {
  82. //IPH = 0x00;
  83. //PX1 = 1;
  84. IPH = 0x04;
  85. IP = 0x00;
  86.         IT1 = 1;   //指定外部中断1下降沿触发,INT0 (P3.3)
  87.         EX1 = 1;   //使能外部中断
  88.         EA = 1;    //开总中断


  89. }

  90. /*------------------------------------------------
  91.                   键值处理
  92. 注:分解显示转换值列表

  93. ------------------------------------------------*/
  94. void Ir_work(void)//红外键值散转程序
  95. {
  96.         TimeNum[5] = TabA[IRcord[0]/16];   //处理客户码并显示
  97.         TimeNum[6] = TabA[IRcord[0]%16];
  98.         TimeNum[8] = TabA[IRcord[1]/16];   //处理客户码并显示
  99.         TimeNum[9] = TabA[IRcord[1]%16];
  100.         TimeNum[11] = TabA[IRcord[2]/16];  //处理数据码并显示
  101.         TimeNum[12] = TabA[IRcord[2]%16];
  102.         TimeNum[14] = TabA[IRcord[3]/16];  //处理数据反码并显示
  103.         TimeNum[15] = TabA[IRcord[3]%16];
  104.         TimeNum[17] = TabA[IRcord[4]/16];  //处理数据反码并显示
  105.         TimeNum[18] = TabA[IRcord[4]%16];
  106.         TimeNum[20] = TabA[IRcord[5]/16];  //处理数据反码并显示
  107.         TimeNum[21] = TabA[IRcord[5]%16];
  108.         irpro_ok=0;//处理完成标志
  109.   }

  110. /***************************************************************/
  111. void Ir_towork(void)//红外键值散转程序
  112. {

  113. //            PutStr(1,0,TimeNum);//显示处理过后的码值
  114.            switch(IRcord[2])//判断第三个数码值
  115.          {
  116.                         case 0x0d:OLED_ShowNum(72,6,46,4,16);break;//o
  117.                         case 0x0c:OLED_ShowNum(0,104,RegBuf_HOLD[0],4,16);break;//1 显示相应的按键值
  118.                         case 0x18:OLED_ShowNum(72,6,456,4,16);break;//2
  119. /***********
  120.                         case 0x5e:LCD1602_Dis_OneChar(4,0,Tab[3]);break;//3
  121.                         case 0x08:LCD1602_Dis_OneChar(4,0,Tab[4]);break;//4
  122.                         case 0x1c:LCD1602_Dis_OneChar(4,0,Tab[5]);break;//5
  123.                         case 0x5a:LCD1602_Dis_OneChar(4,0,Tab[6]);break;//6
  124.                         case 0x42:LCD1602_Dis_OneChar(4,0,Tab[7]);break;//7
  125.                         case 0x52:LCD1602_Dis_OneChar(4,0,Tab[8]);break;//8
  126.                         case 0x4a:LCD1602_Dis_OneChar(4,0,Tab[9]);break;//9
  127.                         case 0x45:LCD1602_Dis_OneChar(4,0,Tab[10]);break;//1
  128.                         case 0x46:LCD1602_Dis_OneChar(4,0,Tab[11]);break;//1
  129.                         case 0x47:LCD1602_Dis_OneChar(4,0,Tab[12]);break;//1
  130.                         case 0x44:LCD1602_Dis_OneChar(4,0,Tab[13]);break;//1
  131.                         case 0x40:LCD1602_Dis_OneChar(4,0,Tab[14]);break;//1
  132.                         case 0x43:LCD1602_Dis_OneChar(4,0,Tab[15]);break;//1
  133.                         case 0x07:LCD1602_Dis_OneChar(4,0,Tab[16]);break;//1
  134.                         case 0x15:LCD1602_Dis_OneChar(4,0,Tab[17]);break;//1
  135.                         case 0x09:LCD1602_Dis_OneChar(4,0,Tab[18]);break;//1   
  136.                         case 0x16:LCD1602_Dis_OneChar(4,0,Tab[19]);break;//1
  137.                         case 0x19:LCD1602_Dis_OneChar(4,0,Tab[20]);break;//1             
  138.              default:break;       
  139. **********/
  140.                   
  141.                          }
  142.                          irpro_ok=0;//处理完成标志                                       
  143. }

  144. /********************************************
  145.                 红外码值处理
  146. *******************************************/
  147. void Ircordpro(void)//红外码值处理函数
  148. {
  149.   unsigned char  i, j, k;
  150.   unsigned char  cord,value;

  151.   k=1;
  152.   for(i=0;i<4;i++)      //处理4个字节
  153.      {
  154.       for(j=1;j<=8;j++) //处理1个字节8位
  155.          {
  156.           cord=irdata[k];
  157.           if(cord>7)//大于某值为1,这个和晶振有绝对关系,这里使用12M计算,此值可以有一定误差
  158.              value|=0x80;
  159.           if(j<8)
  160.                     {
  161.                          value>>=1;
  162.                         }
  163.            k++;
  164.          }
  165.      IRcord[i]=value;
  166.      value=0;
  167. //         tablex(IRcord[2]);     
  168.      }
  169.          irpro_ok=1;//处理完毕标志位置1
  170. }


  171. /******************************************************************
  172. 功能: 初始化
  173. 输入:        站号设置
  174. 输出: 无
  175. 版本: V15.09.0
  176. 作者: 大姆指测控 - 姚工,   QQ:657874307
  177. 修改日期: 2015-09
  178. 说明:,根据P2口低四位编码开关的设置,修改从站地址1-32位,默认都为0则实际地址为1
  179. ******************************************************************/
  180. uchar  Get_ID_HD(void)
  181. {
  182.     uchar temp,i=50;

  183.     P2|=0x0f;//0000 1111
  184.     while(i--);

  185.     temp=~P2;                //P2.0-P2.3接拨码开关,用来设置4位站号 1111 0000
  186.     temp&=0x0f;     //1111 0000&0000 1111 temp = 0000 0000

  187.     if(temp==0)
  188.     {
  189.         return 1;        //站号不能为0,返回默认的1
  190.     }
  191.     return temp;        //返回站号
  192. }

  193. /******************************************************************
  194. 功能: 初始化
  195. 输入:        无
  196. 输出: 无
  197. 版本: V15.09.0
  198. 作者: 大姆指测控 - 姚工,   QQ:657874307
  199. 修改日期: 2015-09
  200. 说明:系统上电之后,先取得系统设置的参数,然后用这些参数来对相应的模块进行初始化,如下:
  201.                 1. 串口通信的波特率 和 校验值 [决定本从机的通信参数];
  202.                 2. modbus 从机的站号 ,可以使用拨码开关来设定站号,或者使用EEPROM存储站号;
  203. ******************************************************************/
  204. void SYSinit(void)
  205. {
  206.        TimesMsinitInt();                                        //Ms定时器初始化,用作产生1ms的系统时间基准
  207.                 OLED_Init();                        //初始化OLED  
  208.                 timer_init();//初始化定时器(打开后出现连接不上问题)
  209.                 EX0init(); //初始化外部中断

  210.     //先写相应的函数,取得系统参数....
  211.     //以下例程使用固定值:19200 ,无校验,
  212.     //站号 =拨码开关设定1-32
  213.     UartInit(19200, NONE_PARITY);                //串口初始化[须要确定好波特率和校验值]
  214.     ModbusInit(Get_ID_HD(),StartSend);         //Modbus串口初始化[须要确定好站号]
  215.     //
  216. //       IP = 0x03;
  217. //       IPH = 0x09;
  218.     EA = 1;

  219. }


  220. //----------------------------START-------------------------------
  221. //=================================================================
  222. void main(void)
  223. {
  224.                
  225. //                u8 Data_p = P2;
  226.                 SYSinit();                                                        //系统初始化

  227. //                numa = 0x01;
  228.                 OLED_Clear();
  229.                 OLED_ShowCHinese(0,0,0);//
  230.                 OLED_ShowCHinese(18,0,1);//
  231.                 OLED_ShowCHinese(36,0,2);//
  232.                 OLED_ShowCHinese(54,0,3);//
  233.                 OLED_ShowCHinese(72,0,4);//
  234.                 OLED_ShowCHinese(90,0,5);//
  235. //                OLED_ShowCHinese(108,0,6);//


  236.     while (1)
  237.     {
  238.         UartRxPoll();                                   //串口数据帧检查处理
  239.         TEST1();
  240.         //......
  241.        //继续添加应用程序代码...
  242.          LED=1;

  243. /******************************
  244. 功能:读寄存器
  245. 调用:RegBuf_Input[0],0为寄存器地址对应30001
  246. *****************************/
  247.                 OLED_ShowNum(0,6,RegBuf_Input[0],4,16);
  248.                 OLED_ShowNum(32,6,RegBuf_Input[1],4,16);
  249.                 OLED_ShowNum(64,6,RegBuf_Input[2],4,16);
  250.                 OLED_ShowNum(96,6,RegBuf_Input[3],4,16);

  251. /******************************
  252. 功能:读写寄存器
  253. 调用:RegBuf_HOLD[0],0为寄存器地址对应40001
  254. *****************************/

  255.                 OLED_ShowNum(0,4,RegBuf_HOLD[0],4,16);//最大16950
  256.                 OLED_ShowNum(32,4,RegBuf_HOLD[1],4,16);//最大16950
  257.                 OLED_ShowNum(64,4,RegBuf_HOLD[2],4,16);//最大16950
  258.                 OLED_ShowNum(96,4,RegBuf_HOLD[3],4,16);//最大16950

  259. //                OLED_ShowNum(0,6,SwBuf_IN[0],4,16);//最大16950
  260. //      OLED_ShowChar(40,6,SwBuf_IN[0]);

  261. /***************测试控制*************/
  262.                 OLED_ShowChar(0,2,TimeNum[5]);
  263.                 OLED_ShowChar(8,2,TimeNum[6]);
  264.                 OLED_ShowChar(16,2,TimeNum[8]);
  265.                 OLED_ShowChar(24,2,TimeNum[9]);
  266.                 OLED_ShowChar(32,2,TimeNum[11]);
  267.                 OLED_ShowChar(40,2,TimeNum[12]);
  268.                 OLED_ShowChar(48,2,TimeNum[14]);
  269.                 OLED_ShowChar(56,2,TimeNum[15]);
  270.                 OLED_ShowChar(64,2,TimeNum[17]);
  271.                 OLED_ShowChar(72,2,TimeNum[18]);
  272.                 OLED_ShowChar(80,2,TimeNum[20]);
  273.                 OLED_ShowChar(88,2,TimeNum[21]);
  274.                 if(irok)                        //如果接收好了进行红外处理
  275.                   {   
  276.          
  277.                    Ircordpro();
  278.                    irok=0;
  279.                   }

  280.                 if(irpro_ok)                   //如果处理好后进行工作处理,如按对应的按键后显示对应的数字等
  281.                   {
  282.                    Ir_work();
  283.                    Ir_towork();
  284.                   }



  285.     }
  286. }
复制代码

我设置测试的,就算设置TOMD=0x30;modbus也会出现不能用,
回复

使用道具 举报

ID:89072 发表于 2021-12-7 16:39 | 显示全部楼层
外部中断1设置优先级0,,定时器1是不是也需要设置优先级1?
回复

使用道具 举报

ID:89072 发表于 2021-12-7 16:50 | 显示全部楼层
本帖最后由 hslcac 于 2021-12-7 16:56 编辑

1638867275553.jpg 8C657041-004A-41c6-9EC5-DA4A7C47B599.png
外部中断1优先级0,定时器1优先级1,设置完后还是读取错误,接收的红外解码FFFFFFFBF7C8B,是时序问题吗?请大神帮忙看一下问题出在哪里啊

回复

使用道具 举报

ID:624769 发表于 2021-12-7 16:59 | 显示全部楼层
当你设置 IP = 0x04的时候

你前面写的 IP = 0x08 就自动无效了,

这个道理你懂得吧?
回复

使用道具 举报

ID:89072 发表于 2021-12-7 17:41 | 显示全部楼层
188610329 发表于 2021-12-7 16:59
当你设置 IP = 0x04的时候

你前面写的 IP = 0x08 就自动无效了,

捕获.PNG
明白了非常感谢
回复

使用道具 举报

ID:89072 发表于 2021-12-7 17:41 | 显示全部楼层
审核通过的慢,发的程序重复了
回复

使用道具 举报

ID:57657 发表于 2021-12-7 18:16 | 显示全部楼层
你这代码都是东拼西凑来的,框架逻辑太乱,根本没法改,只能从头写,并进行一些优化。
回复

使用道具 举报

ID:89072 发表于 2021-12-7 18:18 | 显示全部楼层
IMG_20211207_181323.jpg lQLPDhrwKGuYxMTNAczNAvawfo8PTgh9-poBtretRcA3AA_758_460.png
调试不过啊,解码显示:0000 0000 7E3A
回复

使用道具 举报

ID:89072 发表于 2021-12-7 18:39 | 显示全部楼层
npn 发表于 2021-12-7 18:16
你这代码都是东拼西凑来的,框架逻辑太乱,根本没法改,只能从头写,并进行一些优化。

不乱的,整体的框架是在Modbus的程序上增加的
回复

使用道具 举报

ID:89072 发表于 2021-12-7 19:54 | 显示全部楼层
Modbus程序电路图.7z (3.08 MB, 下载次数: 8)

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:624769 发表于 2021-12-7 20:40 | 显示全部楼层
说实话,看了半天没看明白你有什么问题,以及你想要做什么, 关于你的程序,说实话,年纪大了,那么长一篇代码,还不是自己要用的,真么没有太大耐心分析,就跟你说说浮在表面上的问题吧。
你反复说Modbus怎么怎么, Modbus 不是通信协议么? 有什么能用不能用的说法? 要用到 Modbus 协议,一般是通过串口。不管是485也好,232也好,到了单片机这边,能做的只有 Uart.  你贴的代码也只是部分,我也没精力完全看,但是,如果你用的是硬件Uart 你 interrupt 4 开了么?  然后,如果用的硬件Uart 肯定需要定时器做波特率发生器吧? 那么一般是要用定时器1的吧? TMOD也要设置为 0x20 的吧? 那么,你又说两个定时器一起使用,其中包括了Uart 的定时器1么? 要知道定时器1已经被用作波特率发生器了,除非拆分定时器0,不然你无法把定时器1用来做别的事。

接着在说定时器0,如果你要把定时器0设置为16位定时器,就好像前面IPH的问题,你不能直接去 TMOD = 0x01; 你要考虑你的 TMOD = 0x20;的问题,所以,要么,你干脆点, 一个 TMOD = 0x21;    要么,设置定时器的时候,  分别用  TMOD |= 0x20;  TMOD |= 0x01;   那么才不会影响设置。类似的问题,应该有不少,你最好仔细捋一遍,比如: TMOD 你全文搜索一下,到底多少地方设置了? 有没有覆盖了之前的设置,等等。

暂时想到这些,就写这些。 其实,你的代码,真的,怎么看都是东拼西凑的,因为层次性系统性,完全没有。
回复

使用道具 举报

ID:89072 发表于 2021-12-7 20:58 | 显示全部楼层
188610329 发表于 2021-12-7 20:40
说实话,看了半天没看明白你有什么问题,以及你想要做什么, 关于你的程序,说实话,年纪大了,那么长一篇 ...

非常感谢您的回复,程序就像您说得,我是使用的模块编程的,都是单个调试并借鉴别人的,我自己只做了合并,再此感谢您的解答,我做的是一个远程485状态监控程序,监控输入的状态,并做触屏显示,本来感觉可以实现,由于技术基础确实有限,用PLC成本高,使用的数量又很多,所以调试了很久了才到论坛求助,再此感谢您的指点,谢谢。
回复

使用道具 举报

ID:89072 发表于 2021-12-7 21:09 | 显示全部楼层
188610329 发表于 2021-12-7 20:40
说实话,看了半天没看明白你有什么问题,以及你想要做什么, 关于你的程序,说实话,年纪大了,那么长一篇 ...

定时器1.png
非常感谢前辈您的指点,您说的“其中包括了Uart 的定时器1么?”我返回找到了,还是个人经验不足,再此感谢您,确实是定时器1用了,我又重复使用了定时器1作为红外定时器计时使用,非常感谢。
回复

使用道具 举报

ID:89072 发表于 2021-12-8 07:49 | 显示全部楼层
再次感谢 前辈(188610329 )经过仔细检查,确实是定时器在Modbus里面使用了定时器1和0,关于红外程序需要使用定时器需要使用STC12的void PCA_isr() interrupt 7 using 1,PCA中断定时器,由于我基础没打好,再此和各位学习中的朋友们做交流吧,有能力的可以一试,我也是半路开始学的,
Modbus程序完全可以使用,配合昆仑通态的上位软件做控制与监控没问题,OLED自己可以取模软件修改显示的字,程序中有Modbus说明,地址使用的外部P2.0-P2.3的4个IO口做地址选择控制,485使能使用的P3.2外部中断0,增加自己的程序可以在APP.C中增加,我已做了部分测试, 其余的大家自己研究。
有不懂的可以交流,解决红外定时器问题了帮忙告诉我一下。
回复

使用道具 举报

ID:624769 发表于 2021-12-8 18:20 | 显示全部楼层
hslcac 发表于 2021-12-8 07:49
再次感谢 前辈(188610329 )经过仔细检查,确实是定时器在Modbus里面使用了定时器1和0,关于红外程序需要 ...

你红外线,现在是什么问题? 没有定时器么??

你单片机具体什么型号? 如果 STC12C5A系列的话, 是有独立波特率发生器的,让Uart使用 独立波特率发生器的话,T1就解放出来,可以作为其他的定时器使用了。
回复

使用道具 举报

ID:89072 发表于 2021-12-10 17:38 | 显示全部楼层
188610329 发表于 2021-12-8 18:20
你红外线,现在是什么问题? 没有定时器么??

你单片机具体什么型号? 如果 STC12C5A系列的话, 是有 ...

3C11AA38-FC1E-4b9e-B24A-5FBA920BB1C5.png 448933EA-B4D0-4810-8894-5C8C9B4F5B60.png IMG_20211210_172529.jpg Screenshot_2021-12-10-17-25-14-621_com.duokan.phone.remotecontroller.jpg
感谢前辈的回复,使用的红外遥控做按键设置用,我现在红外的定时器1的TMOD改为0x03后,发现单片机可以解码手机遥控码,并且很稳定,我也没再考虑修改程序,就是有时候上电后出现485延迟信号接收不到问题,您说的穿孔专用的定时器中断,我会继续查资料测试找办法调试,现在运行基本稳定,时间又有限,所以有时间我会在优化的,谢谢您。我是一个单片机爱好者,由于个人时间很少,平时都是回家后查资料学习,没有太多精力去学基础,只有自己做些小的板子,把单独的程序调试好了(还是别人的成熟程序),做模块化合并,遇到问题边学边做的,现已近不惑之年,工作压力也大学习精力有限,有些简单的问题前辈请见谅。
回复

使用道具 举报

ID:89072 发表于 2021-12-10 18:50 | 显示全部楼层
单片机使用的STC12C5A60S2
回复

使用道具 举报

ID:624769 发表于 2021-12-10 19:10 | 显示全部楼层
hslcac 发表于 2021-12-10 18:50
单片机使用的STC12C5A60S2

技术手册, 第 283,284, 297 页, 有关于 专用波特率发生器BRT 的使用说明。

2楼下载611页的:http://www.51hei.com/bbs/dpj-96160-1.html

串口,使用BRT的话,就不会占用定时器T1了。
而且,BRT也只能给串口用,你串口不用BRT,这个资源也是白白浪费的。
回复

使用道具 举报

ID:89072 发表于 2021-12-11 07:42 | 显示全部楼层
188610329 发表于 2021-12-10 19:10
技术手册, 第 283,284, 297 页, 有关于 专用波特率发生器BRT 的使用说明。

好的,谢谢您
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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