登录
首页 PLC论坛 PLC论坛
回帖 发帖
正文

主题:想做一个高速计数器计脉冲,三菱PLC不知道能不能实现。

点击:344 回复:26

能不能从发脉冲的PLC,解决你的问题
25-05-08 20:06
不能,要是能的话,就简单了。发完一次传送一次
25-05-09 08:43
没有它的程序可以理解~不识庐山真面目,只缘身在其外
25-05-09 09:49
最近也想写一个类似的程序
调试XY两个轴运动时发的脉冲数量
方向判断加减计数器
用国产仿三菱似乎只能30HZ以下
不是很稳定
可能还只能使用单片机来做
25-05-12 06:32
程序做好了?能不能发上来给我们学习一下,
25-05-12 11:11
deepseek给我的答案
以下是一个基于STC15W系列单片机的Timer0计数器程序示例,配置为16位计数器模式,支持外部脉冲计数并处理溢出:
```c
#include
#include
unsigned int count_overflows = 0;  // 溢出次数计数器
unsigned long total_count = 0;     // 总脉冲计数
// Timer0初始化函数
void Timer0_Init(void)
{
   TMOD &= 0xF0;   // 清除T0原有配置
   TMOD |= 0x05;   // 设置T0为计数器模式,工作模式1(16位)
   TH0 = 0x00;     // 初始值高字节
   TL0 = 0x00;     // 初始值低字节
   ET0 = 1;        // 使能T0中断
   EA = 1;         // 全局中断使能
   TR0 = 1;        // 启动T0计数器
}
// Timer0中断服务函数
void Timer0_ISR(void) interrupt 1
{
   count_overflows++;  // 溢出次数计数
}
// 获取总脉冲计数
unsigned long Get_Pulse_Count(void)
{
   unsigned int current_count;
   unsigned long result;
   EA = 0;  // 暂停中断
   current_count = (TH0 << 8) | TL0;
   result = (unsigned long)count_overflows * 65536 + current_count;
   EA = 1;  // 恢复中断
   return result;
}
void main(void)
{
   Timer0_Init();  // 初始化Timer0
   while(1)
   {
       total_count = Get_Pulse_Count();  // 获取当前总计数
         // 在此处添加您的处理代码,例如:
       // - 显示计数结果
       // - 通过串口发送数据
       // - 触发其他操作
       // 示例:每50000次计数执行操作
       if(total_count % 50000 == 0){
           // 执行定期操作
       }
   }
}
```
### 程序说明:
1. **工作模式**:
  - 配置为16位计数器模式(模式1)
  - 外部脉冲输入引脚:P3.4(T0引脚)
2. **功能特点**:
  - 自动处理16位溢出(最大计数范围:0~4294967295)
  - 提供获取总脉冲计数的安全读取函数
  - 支持长期连续计数
3. **关键函数**:
  - `Timer0_Init()`:初始化Timer0计数器
  - `Get_Pulse_Count()`:安全获取当前总脉冲数
  - 中断服务程序:自动处理计数器溢出
4. **使用注意事项**:
  - 输入脉冲频率不应超过系统时钟频率的1/24
  - 脉冲高电平持续时间 > 2个系统时钟周期
  - 脉冲低电平持续时间 > 2个系统时钟周期
  - 建议在P3.4引脚增加硬件消抖电路(针对机械开关信号)
### 扩展建议:
1. 如需显示数据,可添加LCD显示驱动代码
2. 如需远程监控,可添加串口通信协议
3. 可添加计数复位功能(复位TH0/TL0和count_overflows)
4. 可添加脉冲频率计算功能(配合定时器测量)
25-05-12 17:38
#include                 //
             #include               //
 #define      uchar  unsigned char
             #define      uint   unsigned int
 uchar        kcounter;
             uchar        kstatus;
 uint     pulse;
 sbit         IntPut0=P3^2;         //
             sbit         IntPut1=P3^3;         //
             sbit         IntPut2=P3^4;         //
             sbit         IntPut3=P3^5;         //
             sbit         OutPut2=P1^3;         //
             sbit         OutPut3=P1^4;         //
             sbit         OutPut4=P1^5;         //
 sbit         KEY1=P5^4;            //
             sbit         KEY2=P5^5;            //
             sbit         KEY3=P1^6;            //
             sbit         KEY4=P1^7;            //
             uint         Count_A=0;            // 总脉冲计数
 uint         Count_B=0;
  bit   CountA_Falg;
  bit   CountB_Falg;
             sbit         OLED_SCL=P1^1;       //
             sbit         OLED_SDA=P1^0;       //
             #define      high 1
             #define      low 0
/*************Pin Define***************/
             void         Initial_LY096BG30();
             void         Delay_50ms(uint Del_50ms);
             void         fill_picture(uchar fill_Data);
             void         IIC_Start();
             void         IIC_Stop();
             void         Write_IIC_Command(uchar IIC_Command);
             void         Write_IIC_Data(uchar IIC_Data);
             bit          Write_IIC_Byte(uchar IIC_Byte);
             void         dis_Value(uchar s);
/***********************0--A字符表*************************/
uchar code show1[]=
{
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,/*"0",0*/
0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,/*"1",1*/
0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,/*"2",2*/
0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,/*"3",3*/
0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,/*"4",4*/
0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,/*"5",5*/
0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,/*"6",6*/
0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,/*"7",7*/
0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,/*"8",8*/
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00,/*"9",9*/
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x1F,0x01,0x01,0x01,0x01,0x1F,0x00,/*"A",10*/
0x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00,0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00,/*"D",11*/
0x08,0xF8,0x00,0xF8,0x00,0xF8,0x08,0x00,0x00,0x03,0x3E,0x01,0x3E,0x03,0x00,0x00,/*"W",12*/
0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00,/*"O",13*/
0x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08,0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00,/*"N",14*/
};
/***********************0--A字符表*************************/
uchar code show2[]=
{
//电(0) 机(1) 开(2) 关(3) 一(4) 二(5) 三(6) 四(7) 五(8) 六(9) 七(10) 八(11) 九(12) 十(13)
0x00,0x00,0xF8,0x88,0x88,0x88,0x88,0xFF,0x88,0x88,0x88,0x88,0xF8,0x00,0x00,0x00,
0x00,0x00,0x1F,0x08,0x08,0x08,0x08,0x7F,0x88,0x88,0x88,0x88,0x9F,0x80,0xF0,0x00,/*"电",0*/
0x10,0x10,0xD0,0xFF,0x90,0x10,0x00,0xFE,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,0x00,
0x04,0x03,0x00,0xFF,0x00,0x83,0x60,0x1F,0x00,0x00,0x00,0x3F,0x40,0x40,0x78,0x00,/*"机",1*/
0x80,0x82,0x82,0x82,0xFE,0x82,0x82,0x82,0x82,0x82,0xFE,0x82,0x82,0x82,0x80,0x00,
0x00,0x80,0x40,0x30,0x0F,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,/*"开",2*/
0x00,0x00,0x10,0x11,0x16,0x10,0x10,0xF0,0x10,0x10,0x14,0x13,0x10,0x00,0x00,0x00,
0x81,0x81,0x41,0x41,0x21,0x11,0x0D,0x03,0x0D,0x11,0x21,0x41,0x41,0x81,0x81,0x00,/*"关",3*/
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*"一",4*/
0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00,0x00,
0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,/*"二",5*/
0x00,0x04,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x04,0x00,0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,/*"三",6*/
0x00,0xFC,0x04,0x04,0x04,0xFC,0x04,0x04,0x04,0xFC,0x04,0x04,0x04,0xFC,0x00,0x00,
0x00,0x7F,0x28,0x24,0x23,0x20,0x20,0x20,0x20,0x21,0x22,0x22,0x22,0x7F,0x00,0x00,/*"四",7*/
0x00,0x02,0x42,0x42,0x42,0xC2,0x7E,0x42,0x42,0x42,0x42,0xC2,0x02,0x02,0x00,0x00,
0x40,0x40,0x40,0x40,0x78,0x47,0x40,0x40,0x40,0x40,0x40,0x7F,0x40,0x40,0x40,0x00,/*"五",8*/
0x20,0x20,0x20,0x20,0x20,0x20,0x21,0x22,0x2C,0x20,0x20,0x20,0x20,0x20,0x20,0x00,
0x00,0x40,0x20,0x10,0x0C,0x03,0x00,0x00,0x00,0x01,0x02,0x04,0x18,0x60,0x00,0x00,/*"六",9*/
0x80,0x80,0x80,0x80,0x80,0x40,0xFF,0x40,0x40,0x40,0x20,0x20,0x20,0x20,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x40,0x40,0x40,0x40,0x40,0x40,0x78,0x00,0x00,/*"七",10*/
0x00,0x00,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0x7E,0x80,0x00,0x00,0x00,0x00,0x00,
0x00,0x80,0x60,0x18,0x07,0x00,0x00,0x00,0x00,0x00,0x03,0x0C,0x30,0x40,0x80,0x00,/*"八",11*/
0x00,0x10,0x10,0x10,0x10,0xFF,0x10,0x10,0x10,0x10,0xF0,0x00,0x00,0x00,0x00,0x00,
0x80,0x40,0x20,0x18,0x07,0x00,0x00,0x00,0x00,0x00,0x3F,0x40,0x40,0x40,0x78,0x00,/*"九",12*/
0x40,0x40,0x40,0x40,0x40,0x40,0x40,0xFF,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*"十",13*/
};
/**************Delay*******************************/
             void   Delay_50ms(uint Del_50ms)        //
             {
              uint m;
              for(;Del_50ms>0;Del_50ms--)
              for(m=62450;m>0;m--);
             }
/*******************IIC Start******************/
             void IIC_Start()
             {
              OLED_SCL=high;
              OLED_SDA=high;
              _nop_();
              OLED_SDA=low;
              _nop_();_nop_();
              OLED_SCL=low;
             }
/*************IIC Stop*************************/
             void IIC_Stop()
             {
             OLED_SDA=low;
             _nop_();
             OLED_SCL=high;
             _nop_();_nop_();
             OLED_SDA=high;
             }
/*****************IIC Write byte***************/
             bit Write_IIC_Byte(unsigned char IIC_Byte)
             {
             unsigned char i;
              bit Ack_Bit;                      //应答信号
              for(i=0;i<8;i++)
              {
              if(IIC_Byte & 0x80)               //1?0?
              OLED_SDA=high;
              else
              OLED_SDA=low;
              OLED_SCL=high;
              _nop_();_nop_();
              OLED_SCL=low;
              IIC_Byte<<=1;                     //loop
              }
             OLED_SDA=high;                     //释放IIC SDA总线为主器件接收从器件产生应答信号
             _nop_();_nop_();
             OLED_SCL=high;                     //第9个时钟周期
             _nop_();_nop_();
             Ack_Bit=OLED_SDA;                  //读取应答信号
             OLED_SCL=low;
             return Ack_Bit;
             }
/*************IIC Write Command*****************/
             void Write_IIC_Command(unsigned char IIC_Command)
             {
             IIC_Start();
             Write_IIC_Byte(0x78);              //Slave address,SA0=0
             Write_IIC_Byte(0x00);              //write command
             Write_IIC_Byte(IIC_Command);
             IIC_Stop();
             }
/****************IIC Write Data*****************/
             void Write_IIC_Data(uchar IIC_Data)
             {
             IIC_Start();
             Write_IIC_Byte(0x78);
             Write_IIC_Byte(0x40);              //write data
             Write_IIC_Byte(IIC_Data);
             IIC_Stop();
             }
/********************picture**********************/
             void Clear_disp()
             {
             uchar x,y;
             for(y=0;y<8;y++)
              {
              Write_IIC_Command(0xb0+y);
              Write_IIC_Command(0x00);
              Write_IIC_Command(0x10);
               for(x=0;x<128;x++)               //横向像素
               {
               Write_IIC_Data(0X00);
               }
              }
             }
/***********************Initial code*********************/
             void  Initial_LY096BG30()
             {
             Write_IIC_Command(0xAE);   //display off
             Write_IIC_Command(0x20);   //Set Memory Addressing Mode
             Write_IIC_Command(0x10);     //00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid
             Write_IIC_Command(0xb0);     //Set Page Start Address for Page Addressing Mode,0-7
             Write_IIC_Command(0xc8);      //Set COM Output Scan Direction
             Write_IIC_Command(0x00);   //---set low column address
             Write_IIC_Command(0x10);   //---set high column address
             Write_IIC_Command(0x40);   //--set start line address
             Write_IIC_Command(0x81);   //--set contrast control register
             Write_IIC_Command(0x7f);
             Write_IIC_Command(0xa1);   //--set segment re-map 0 to 127
             Write_IIC_Command(0xa6);   //--set normal display
             Write_IIC_Command(0xa8);   //--set multiplex ratio(1 to 64)
             Write_IIC_Command(0x3F);   //
             Write_IIC_Command(0xa4);   //0xa4,Output follows RAM content;0xa5,Output ignores RAM content
             Write_IIC_Command(0xd3);   //-set display offset
             Write_IIC_Command(0x00);   //-not offset
             Write_IIC_Command(0xd5);   //--set display clock divide ratio/oscillator frequency
             Write_IIC_Command(0xf0);   //--set divide ratio
             Write_IIC_Command(0xd9);   //--set pre-charge period
             Write_IIC_Command(0x22);   //
             Write_IIC_Command(0xda);   //--set com pins hardware configuration
             Write_IIC_Command(0x12);
             Write_IIC_Command(0xdb);   //--set vcomh
             Write_IIC_Command(0x20);   //0x20,0.77xVcc
             Write_IIC_Command(0x8d);   //--set DC-DC enable
             Write_IIC_Command(0x14);   //
             Write_IIC_Command(0xaf);   //--turn on oled panel
            }
/****************按键计数器状态寄存器归零*************/
             void RstKey(void)
             {
             kcounter=0;                        //按键计数器归零
             kstatus=0;                         //状态寄存器归零
             }
/*****************按键低电平检测函数*****************/
             void   LowVoltKey(void)            //按键计数器状态标志加一
             {
             kcounter++;
             kstatus++;
             _nop_();                           //延时
             }
/*****************按键低电平检测函数*****************/
             void   HighVoltKey(void)
 {
             kcounter++;
             kstatus=0;
             _nop_();                           //延时
             }
/*****16X16中文字体显示子程序 dd字符数组地址***/
/***xx横向坐标 10~17 yy竖向坐标B0 B2 B4 B6***/
/***void Display(0x10,0XB0,0X00)***/
             void Display(uchar xx,yy, uint dd)
             {
             uchar x,y;
             uint  i=0;
             uint  Cnt=32;
             for(y=0;y<2;y++)
              {
              Write_IIC_Command(yy+y);          //竖向第yy行    yy=0XB0 0XB2 0XB4 0XB6
              Write_IIC_Command(0x00);          //
              Write_IIC_Command(xx);               //横向第XX个字
               for(x=0;x<16;x++)                     //横向像素
               {
               Write_IIC_Data(show2[x+y*16+Cnt*dd]); //字符表第dd个字
               }
              }
             }
/*****************脉冲计数器显示****************/
             void DisCountA(uint Count)
             {
              uchar A1,A2,A3,A4;
              uchar x,y;
              uint i=0;
              A1=Count/1000;
              A2=(Count-A1*1000)/100;
              A3=(Count-A1*1000-A2*100)/10;
              A4=Count-A1*1000-A2*100-A3*10;
              for(y=0;y<2;y++)                  //百位显示
              {
              Write_IIC_Command(0XB0+y);        //纵向页
              Write_IIC_Command(00);            //横向离左部边缘开始的距离
              Write_IIC_Command(0X14);          //横向第四个字
               for(x=0;x<8;x++)                 //横向像素
               {
               Write_IIC_Data(show1[x+y*8+A1*16]);     //千位显示 0--A字符表
               }
               for(x=0;x<8;x++)                 //横向像素
               {
               Write_IIC_Data(show1[x+y*8+A2*16]);    //百位显示
               }
              }
              for(y=0;y<2;y++)
               {
               Write_IIC_Command(0XB0+y);            //纵向页
               Write_IIC_Command(00);                //横向离左部边缘开始的距离
               Write_IIC_Command(0X15);              //横向第五个字
                for(x=0;x<8;x++)                     //横向像素
                {
                Write_IIC_Data(show1[x+y*8+A3*16]);  //十位位显示
                }
                for(x=0;x<8;x++)                     //横向像素
                {
                Write_IIC_Data(show1[x+y*8+A4*16]);    //个位显示
                }
               }
             }                          
/*****************脉冲计数器显示****************/
             void DisCountB(uint Count)
             {
             uchar A1,A2,A3,A4;
              uchar x,y;
              uint i=0;
              A1=Count/1000;
              A2=(Count-A1*1000)/100;
              A3=(Count-A1*1000-A2*100)/10;
              A4=Count-A1*1000-A2*100-A3*10;
              for(y=0;y<2;y++)                  //百位显示
              {
              Write_IIC_Command(0XB2+y);        //纵向页
              Write_IIC_Command(00);            //横向离左部边缘开始的距离
              Write_IIC_Command(0X14);          //横向第四个字
               for(x=0;x<8;x++)                 //横向像素
               {
               Write_IIC_Data(show1[x+y*8+A1*16]);     //千位显示 0--A字符表
               }
               for(x=0;x<8;x++)                 //横向像素
               {
               Write_IIC_Data(show1[x+y*8+A2*16]);    //百位显示
               }
              }
              for(y=0;y<2;y++)
               {
               Write_IIC_Command(0XB2+y);            //纵向页
               Write_IIC_Command(00);                //横向离左部边缘开始的距离
               Write_IIC_Command(0X15);              //横向第五个字
                for(x=0;x<8;x++)                     //横向像素
                {
                Write_IIC_Data(show1[x+y*8+A3*16]);  //十位位显示
                }
                for(x=0;x<8;x++)                     //横向像素
                {
                Write_IIC_Data(show1[x+y*8+A4*16]);    //个位显示
                }
               }
            }
/***************************************/
     void exint0() interrupt 0       //INT0中断入口
             {
 CountA_Falg=1;
 if(!IntPut2)
 Count_A--;
             else
         Count_A++;
             }
/***************************************/
             void exint1() interrupt 2       //INT1中断入口
             {
             CountB_Falg=1;
 if(!IntPut3)
 Count_B--;
             else
         Count_B++;
             }
/***************************************/
             void  main()                       //
             {
              P1M0=0X00;                        //1.0~1.5准双向输入
              P1M1=0X00;                        //1.6~1.7推挽输出
              P3M0=0X00;                        //准双向输入
              P3M1=0X00;                        //准双向输入
              P5M0=0X30;                        //
              P5M1=0X00;                        //
  IT0 = 1;                    //设置INT0的中断类型 (1:仅下降沿 0:上升沿和下降沿)
              EX0 = 1;                    //使能INT0中断
  IT1 = 1;                    //设置INT0的中断类型 (1:仅下降沿 0:上升沿和下降沿)
              EX1 = 1;                    //使能INT0中断
              EA=1;                             //
              Count_A=0;
              Initial_LY096BG30();
              Clear_disp();
              Delay_50ms(20);
              Display(0X17,0XB0,1); //
  DisCountA(Count_A);
  DisCountB(Count_B);
  RstKey();
  LowVoltKey();
  HighVoltKey();
  while(1)                          //
               {
if(CountA_Falg==1)
{
 CountA_Falg=0;
 DisCountA(Count_A);
}
if(CountB_Falg==1)
{
 CountB_Falg=0;
 DisCountB(Count_B);
}
//
RstKey();
                for(;kcounter<10;)              //按键循环5次
                 {
                  if(!KEY1)                  //按键低电平
                  {
                  LowVoltKey();                 //按键低电平 清除计数器
                  }
                  else if(~!KEY1)            //按键高电平
                  {
                  HighVoltKey();                //按键计数器加一 状态计数器加一
                  }
                 }
                if(kstatus>=8)                 /*按键状态标志大于等于3为有效值*/
                {
 pulse=0;
 for(;pulse<50;)
 {
 pulse++;
 OutPut2=~OutPut2;
 Delay_50ms(1);
 }
}
//
                RstKey();
                for(;kcounter<10;)              //按键循环5次
{
                 if(!KEY2)                  //按键低电平
                 {
                  LowVoltKey();                 //按键低电平 清除计数器
                  }
                  else if(~!KEY2)            //按键高电平
                  {
                  HighVoltKey();                //按键计数器加一 状态计数器加一
                  }
                 }
                if(kstatus>=8)                 /*按键状态标志大于等于3为有效值*/
                {
 pulse=0;
 for(;pulse<50;)
 {
 pulse++;
 OutPut3=~OutPut3;
 Delay_50ms(1);
 }
}
//
              }                                //
             }                                  //L421 CODE2310
25-05-13 10:26

上一页 上一页

工控新闻

更多新闻资讯