首页 > 其他分享 >利用西门子DQ模块控制移位寄存器,模拟串行通信

利用西门子DQ模块控制移位寄存器,模拟串行通信

时间:2024-06-06 13:22:16浏览次数:20  
标签:statShiftregister END statShiftArr time .% IO 寄存器 串行 DQ

1. 背景

  • 以前了解过串行通信的方法但是没有详细了解过具体实现。趁着手上有的一堆破铜烂铁尝试自己去实现一个最简单的串行控制。
    目的是通过移位寄存器的不同位的表达,达到2*2=4个的继电器管断组合,达到切换矩阵的目的。
    这里只记录一下程序实现,不记录硬件电路。

2. 材料

  • 移位寄存器:SN74AHC594
  • 固态继电器:4个
  • 电源模块及外围器件,若干
  • CPU1500+DQ16

3. 原理

  • 选择的是一个8位移位寄存器,当响应bit等于1的时候,动作相应的继电器,组合应用。
  • 移位寄存器的时钟(CLOCK)上升沿的时候会把对应的数据(DATA)状态传出(左移)。
  • 8位数据传递完成后,片选信号(CS)拉高,完成一次数据传递过程。片选信号不用依靠时钟传递。

4. 程序过程

  • 写入数据选择
//for 2 - 2 switch module

//1.select number
IF #IO_enable AND NOT #IO_reset THEN
    #statSwitchNbr := #I_switch_nbr;
END_IF;

CASE #statSwitchNbr OF
        //default
    0:
        #statShiftregister := 2#00000000;
        //normal
    10:
        #statShiftregister := 2#01100010;
        //cross
    20:
        #statShiftregister := 2#00010100;
        //short
    30:
        #statShiftregister := 2#00000110;
        //short
    40:
        #statShiftregister := 2#01110000;
        //wire break
    50:
        #statShiftregister := 2#00000000;
    ELSE
        //others
        #statShiftregister := 2#11111111;
END_CASE;
//#tmpRel := Serialize(SRC_VARIABLE := #statShiftregister, DEST_ARRAY => #statShiftArr, POS := #tmpPos);
#statShiftArr[7] := #statShiftregister.%X0;
#statShiftArr[6] := #statShiftregister.%X1;
#statShiftArr[5] := #statShiftregister.%X2;
#statShiftArr[4] := #statShiftregister.%X3;
#statShiftArr[3] := #statShiftregister.%X4;
#statShiftArr[2] := #statShiftregister.%X5;
#statShiftArr[1] := #statShiftregister.%X6;
#statShiftArr[0] := #statShiftregister.%X7;
  • 时钟信号
    • 按照以前做的两个定时器实现高低电平切换的方法实现了此处的时钟信号
//2. clock
#data_clock(In_switchtime := T#1000ms,
            In_startAlternate := #IO_enable,
            Out_switchtime_up=>#statClock_up,
            Out_switchtime_Down=>#statClock_down);
  • 数据写入信号
    • 时钟信号的低电平半区内,等待一小段时间后写入数据(等待是为了数据写入稳定)。写入数据后,时钟信号的高电平脉冲会触发数据写进移位寄存器内。一个循环结束。
//3. shift register
#time_data(IN := #statClock_down,
           PT := T#500ms);

//4. output data
IF #IO_enable AND NOT #IO_reset THEN
    IF #time_data.Q AND NOT #statPulserArr[0] THEN
        #O_Data := #statShiftArr[#statData_count];
        #statData_count := #statData_count + 1;
    END_IF;
    #statPulserArr[0] := #time_data.Q;
END_IF;
  • 数据发送完成后,片选信号激活
//6. output cs
#time_cs(IN:=#statClock_up,
         PT:=T#100MS);

IF #statData_count > 7 AND #time_cs.Q THEN
    #statCS := true;
END_IF;
#O_cs := #statCS;
  • 完成数据发生,以及复位功能实现
//7. finish
#time_finish(IN:=#statCS,
             PT:=t#100MS);
IF #time_finish.Q THEN
    #statCS := false;
    #IO_enable := false;
    #IO_reset:=false;
    #statData_count := 0;
    RESET_TIMER(#time_data);
    RESET_TIMER(#time_cs);
    RESET_TIMER(#time_finish);
END_IF;
    
//8. reset
IF #IO_reset AND NOT #statPulserArr[2] THEN
    #statSwitchNbr := 0;
    #IO_enable := false;
END_IF;
#statPulserArr[2] := #IO_reset;
#time_reset(IN := #IO_reset,
            PT := t#50ms,
            Q => #statReset);
IF #statReset THEN
    #IO_enable := true;
END_IF;

5. 整体代码如下

//for 2 - 2 switch module

//1.select number
IF #IO_enable AND NOT #IO_reset THEN
    #statSwitchNbr := #I_switch_nbr;
END_IF;

CASE #statSwitchNbr OF
        //default
    0:
        #statShiftregister := 2#00000000;
        //normal
    10:
        #statShiftregister := 2#01100010;
        //cross
    20:
        #statShiftregister := 2#00010100;
        //short
    30:
        #statShiftregister := 2#00000110;
        //short
    40:
        #statShiftregister := 2#01110000;
        //wire break
    50:
        #statShiftregister := 2#00000000;
    ELSE
        //others
        #statShiftregister := 2#11111111;
END_CASE;
//#tmpRel := Serialize(SRC_VARIABLE := #statShiftregister, DEST_ARRAY => #statShiftArr, POS := #tmpPos);
#statShiftArr[7] := #statShiftregister.%X0;
#statShiftArr[6] := #statShiftregister.%X1;
#statShiftArr[5] := #statShiftregister.%X2;
#statShiftArr[4] := #statShiftregister.%X3;
#statShiftArr[3] := #statShiftregister.%X4;
#statShiftArr[2] := #statShiftregister.%X5;
#statShiftArr[1] := #statShiftregister.%X6;
#statShiftArr[0] := #statShiftregister.%X7;


//2. clock
#data_clock(In_switchtime := T#1000ms,
            In_startAlternate := #IO_enable,
            Out_switchtime_up=>#statClock_up,
            Out_switchtime_Down=>#statClock_down);

//3. shift register
#time_data(IN := #statClock_down,
           PT := T#500ms);

//4. output data
IF #IO_enable AND NOT #IO_reset THEN
    IF #time_data.Q AND NOT #statPulserArr[0] THEN
        #O_Data := #statShiftArr[#statData_count];
        #statData_count := #statData_count + 1;
    END_IF;
    #statPulserArr[0] := #time_data.Q;
END_IF;

//5. output clock
#O_clk := #statClock_up;

//6. output cs
#time_cs(IN:=#statClock_up,
         PT:=T#100MS);

IF #statData_count > 7 AND #time_cs.Q THEN
    #statCS := true;
END_IF;
#O_cs := #statCS;

//7. finish
#time_finish(IN:=#statCS,
             PT:=t#100MS);
IF #time_finish.Q THEN
    #statCS := false;
    #IO_enable := false;
    #IO_reset:=false;
    #statData_count := 0;
    RESET_TIMER(#time_data);
    RESET_TIMER(#time_cs);
    RESET_TIMER(#time_finish);
END_IF;
    
//8. reset
IF #IO_reset AND NOT #statPulserArr[2] THEN
    #statSwitchNbr := 0;
    #IO_enable := false;
END_IF;
#statPulserArr[2] := #IO_reset;
#time_reset(IN := #IO_reset,
            PT := t#50ms,
            Q => #statReset);
IF #statReset THEN
    #IO_enable := true;
END_IF;

6. 调试过程

  • 刚开始的脉冲,如图标记出来的其实是被扔掉的。程序里面一共会记录8个上升脉冲,但是标记的这一个被先进先出挤掉了。当然针对这种情况,也可以通过程序把时钟的第一个上升沿过滤掉,但是没有必要,因为这个数据本身就会被移位寄存器扔掉,移位寄存器只记录了从最后一个数据开始倒数8位数据长度。

  • 按照程序的写法,此时发送的数据是2#01100010,所以观察的时钟的每一个上升沿,按照时间顺序应该是0->1->1->0->0->0->1->0

  • 结束时候片选信号如下,因为enable结束的时刻把所有过程信号都清零了,所以最后一个时钟高电平很短。

标签:statShiftregister,END,statShiftArr,time,.%,IO,寄存器,串行,DQ
From: https://www.cnblogs.com/xiacuncun/p/18234879

相关文章

  • 标志寄存器
    标志寄存器EFLAGS寄存器 1.进位标志CF运算结果的最高位产生进位或者借位,那么CF=1注:前提是要确定数据宽度2.奇偶标志PF反映运算结果中'1'的个数,若个数为偶PF=1,为奇则PF=0注:结果转为二进制,数1的个数3.辅助进位标志AF1)在字操作时,发生低字节向高字节进位或者借位时,AF=12)......
  • 用Redisson的延迟队列RDelayedQueue处理延迟任务或者定时任务
    什么是RedissonRedisson在基于NIO的Netty框架上,充分的利用了Redis键值数据库提供的一系列优势,在Java实用工具包中常用接口的基础上,为使用者提供了一系列具有分布式特性的常用工具类。什么是RDelayedQueue获取RDelayedQueue:public<V>RDelayedQueue<V>getDelayedQueue(R......
  • 8086 汇编笔记(十):标志寄存器
    前言一、ZF标志ZeroFlag,零标记位。用于记录相关指令执行后,其结果是否为0。如果结果为0,则ZF=1,如果结果非0,则ZF=0 movax,1subax,1;ZF=1movax,2subax,1;ZF=0二、PF标志ParityFlag,奇偶标记位。它用于记录相关指令执行后,其结果的所有bit位中1的个......
  • 51单片机学习记录-06-LED点阵屏(74HC595移位寄存器)
    1 74HC595是串行输入并行输出的移位寄存器,可用3根线输入串行数据,8根线输出并行数据,多片级联后,可输出16位、24位、32位等,常用于IO口扩展。2 74HC595原理图上升沿移位SERCLK,上升沿锁存RCLK点阵屏MATRIX函数sbitRCK=P3^5; //RCLKsbitSCK=P3^6; //SRCLKsbitSER=P3......
  • 【Proteus】使用移位寄存器实现对汽车尾灯的控制
    1.使用数据选择器74实现移位寄存器!!!2.使用逻辑开关、门电路、LED灯、电阻模拟汽车尾灯电路实验内容:1.使用J-K触发器设计一个汽车尾灯左转向模拟电路。使用LED电平显示器(编号5-8以及13-16)模拟汽车尾灯,当逻辑电平开关K1置低电平时,汽车正常行驶,所......
  • 服饰内衣商家如何通过ADQ投流成功起号跑通高客单?
    在当今的电商时代,流量是每个商家都渴望的资源。对于服饰内衣商家来说,如何通过投放广告吸引目标客户,提高品牌知名度和销售额,是他们面临的重要问题。本文将通过具体的例子,详细介绍服饰内衣商家如何通过ADQ投流成功起号并跑通高客单,从而提高销售效果。图片来自:视觉中国......
  • 使用DQN 来优化车间排产JSP探索
    首先感谢莫烦大神的python强化学习的教程让我能快速了解强化学习自从几年前从事智能工厂建设工作,对于APS听到最多的就是APS上线失败的案例。让自己开始思考APS上线的难度到底在哪里?可能主要原因是APS动态性问题待解决,信息化孤岛的问题。动态性主要是客户订单变化、现场生产......
  • 嵌入式单片机寄存器操作与实现方法
       大家好,今天给大家分享一下,单片机中寄存器该如何操作与实现。“芯片里面的寄存器访问方式一般是: 1.可使用地址访问,2.可使用指令访问,3.不可访问”第一:挂载到内存地址总线上了的挂载到内存地址总线上了的,可以使用分配到的地址访问如下是STM32单片机存储器映像上挂载......
  • 指令指针和寄存器:深入理解及其计算与操作
    在计算机科学中,指令指针和寄存器是两个关键的概念,它们在处理器执行指令时起着重要作用。本文将详细讲解指令指针和寄存器的基本概念,探讨指令指针的计算和操作,帮助读者深入理解这些底层硬件的工作原理。一、指令指针和寄存器的基本概念1.1指令指针指令指针(InstructionP......
  • Mysql DQL 数据查询语言
    查询selectcolumnName1,....from<tableName>;select*from<tableName>;where子句条件= --等于!=,<> --不等于> --大于< --小于>=,<= --大于等于,小于等于betweenand --区间查询多条件whereand/or/notlike子句对查询结果的处理计算列se......