tag 标签: 时序

相关帖子
相关博文
  • 热度 3
    2021-4-20 13:07
    2385 次阅读|
    3 个评论
    当RS485隔离遇见Freemodbus,你碰到问题了吗?
    摘要: 基于 RS485 物理接口的 Modbus 总线在工业控制中广泛应用。 Freemodbus 是一个免费的实用的协议栈,孔丙火(微信公众号:孔丙火)用它实现了一个从站。串口收发信号和 RS485 芯片的收发使能信号采用光耦进行了隔离,在测试过程发现了偶尔出现 TimeOut 的问题,经过查找及分析,发现是光耦信号延时导致的,给出了解决方案,并对问题进行了详细分析。 关键词: RS485 隔离 Freemodbus 光耦 时序 1. 问题来源 工业应用中,在进行 RS485 电路设计的时候,为了确保电气安全和抗干扰性,经常会做信号隔离,光耦隔离是常用的一种形式。 Modbus 协议是现场总线协议中比较常见的一种,其设计和使用简单,运行可靠,在可编程控制器、仪器仪表、传感器中使用广泛,其中,基于 RS485 物理接口的 Modbus 总线使用最多。 Modbus 是主从式的通信结构,一个系统中仅有一个主站,其他为从站。 Freemodbus 是一个免费的协议栈,仅支持从站。 Freemodbus 有专门的机构在维护,比较成熟,相对于自己编写的协议代码,运行更稳定,是开发者在研发时的常用选项。 近来,孔丙火(微信公众号:孔丙火)在设计一个基于 Modbus-RTU 接口的信号采集站,作为从站,把采集到的信号传输给 PLC 等主站设备。单片机采用 STM32F103C8T6 , RS485 芯片: SP485EEN ,接收和发送的隔离采用光耦 PC410 , 485 收发使能信号的隔离采用光耦 EL357NB 。 RS485 部分的原理图如图 1 所示。 图 1 程序设计中,采用 Freemodbus 协议栈实现 Modbus-RTU 协议,串口速率为 115200bps ,数据位 8 位,停止位 1 位,无校验。 在使用 Modbus 主站软件( Modbus Poll )进行调试的过程中,孔丙火(微信公众号:孔丙火)发现通信过程中会出现 TimeOut 的错误,有以下几个特点: a )并不是每一帧都会出错,但会不定时地出现; b )主站询从站的频率越高,出错的几率越低,主站每 30ms 询一帧数据的时候基本不出错,但每 500ms 或 1000ms 询一次的时候,就会比较明显地出错。 2. 查找过程 由于硬件电路是之前使用过的,刚开始并没有考虑是电路的问题。首先是从软件开始查找的。由于能够正常的回复数据,只是偶尔出错,因此软件的整体流程应该是通的,只是某个代码的细节有问题,孔丙火(微信公众号:孔丙火)把代码整个重新捋了一遍,也没有发现明显的问题。 后来,开始逐步排查,先把 RS485 部分的电路短接掉,用 USB-TTL 转换器直接连接单片机的串口收发管脚,进行收发数据的测试,结果一切都正常,无论主站的询问数据周期是多少,都不会出错。于是开始怀疑跟 485 相关的代码。 搞过 485 电路的朋友都知道, 485 电路仅仅是实现一个电平转换,另外由于 485 是半双工,需要外加一个收发使能控制, 485 芯片 实现 TTL 电平与差分电平的转换。涉及到代码,就是多一个管脚,用来控制收发使能。虽然这一步没有测试出问题,但在反复试的过程中,倒是有一点意外收获,孔丙火(微信公众号:孔丙火)分享一下。使能 485 芯片的发送语句,必须在使能串口发送中断(发送为空中断)之前,否则通信是无法成功的。原因分析:发送为空中断在使能后,是立即进入中断的,使能 485 发送的代码无法执行,发送没有使能,但已开始发送数据,这种情况下,发送是肯定不会成功的。这个点给我了启发,是不是发送的时序有问题,导致发送失败呢? 于是开始分析 485 的收发电路,由于信号是隔离的,最有可能出现问题的地方是光耦,就从光耦开始查起。开始查阅 PC410 和 EL357NB 的数据手册,开始是担心光耦前后的限流电阻跟光耦的电流传输比是不是不匹配,导致光耦导通不充分,后经分析电路参数没有问题。然后开始分析光耦的时序,经过光耦隔离的信号肯定会延时,延时的不同步会不会导致问题呢?果然, PC410 和 EL357NB 的传输延时还是有差别的, PC410 的传输延时在几十 ns ,而 EL357NB 的传输延时在 1us 左右,程序代码做了如下修改:在使能 485 发送管脚后,延时一段时间后( 1us 左右,无需太精确),再使能串口的发送中断,经测试, TimeOut 的错误了。 3. 结论及分析 ( 1 )问题就出在光耦的信号传输延时上,在 485 电路的设计之初,单片机的串口收发脚采用高速光耦进行隔离,收发使能脚由于不需要频繁切换,采用一般光耦即可。正是由于这个设计,在使能 485 收发和使能发送中断同时执行的时候,在单片机的串口发送部分(从发送缓存区到硬件管脚,单片机内部完成,无需用户代码干预)处理比较快的时候,就会导致 485 还没有使能发送状态,单片机已开始向 485 芯片发送数据,就会导致发送出错, Modbus 主站软件( Modbus Poll )收到的是不完整的错误的帧,就是看到的 TimeOut 错误。但在单片机的串口发送部分处理的不那么快的时候,就不会出现这个错误,这是错误不定时出现的原因。 ( 2 ) 使能 485 发送管脚后的延时,不能采用 HAL_Delay() 函数, Freemodbus 协议栈的收发使能在 vMBPortSerialEnable() ,由于在调此函数之前已经禁掉了中断,而 HAL_Delay() 函数是基于系统时钟中断定时的,因此不能使用。由于此处不需要精确地定时,只要能满足两种光耦延时的时间差即可,可以使用空语句进行定时,大体算一下时间即可。孔丙火(微信公众号:孔丙火)的代码如图 2 所示。 图 2 ( 3 )在最初的问题中,为什么主站询的快的时候错误少,反而询的慢的时候错误多?这个问题没有完全思考清楚,但孔丙火(微信公众号:孔丙火)有一些心得。元器件都会有一些寄生电容,在电平转换的时候,可以认为电容要先进行充电或放电,因此会有一个斜坡,在主站询的快的时候,电平转换快,在电平改变的时候,电容在上一次的过程中还没有完全放电或充电完毕,这个时候进行反方向的改变需要的时候就会短,可以对冲两种光耦时间差的影响。不知道我这种说法大家是否可以理解,更深层次或者更确切的原因,也欢迎高手指点,或者大家行进讨论。 文章在公众号( 孔丙火 )同步推出,欢迎查看更多系列文章。 单片机、ARM、现场总线、PLC、嵌入式软硬件的设计经验分享,秉承“点点滴滴皆智慧”的理念,以实际项目为单元阐述知识点,一起分享,共同交流。
  • 热度 1
    2019-8-6 11:21
    2202 次阅读|
    0 个评论
    BMD64与BMD128比较
    结合排查之前pio_writeReadBack_test0测试出现的问题,需要参考前人写的相关博客,大部分都是基于BMD64,而我的示例是基于BMD128。 pio_writeReadBack_test0测试HOST发起一个MEM32写,然后再启动MEM32读回,所以先要探究MEM32写,分析 BMD RX 引擎(用于接收、解析TLP ) 。下图是https://blog.csdn.net/ningjinghai11/article/details/80924209博文中给出的BMD64模式下的MEM32写时序仿真图,可以看到存储器写请求TLP有2个,所以相应的bmd_64_rx_state分别有MEM_WR32_QW1和MEM_WR32_WT两个状态对应。 而我在仿真BMD128模式时,由于数据位宽为128bit,所以存储器写只有一个128bit的TLP就足够,而bmd_rx_state只一个MEM_WR32_WT就结束并进入RST状态,具体时序图如下: ( 注 :BMD_MEM_RD32_FMT_TYPE 和BMD_MEM_WR32_FMT_TYPE 两种标头对应的TLP是以PIO的模式传输,所以只会传输一个DW数据,再加上3DW标头;所以在BMD64模式下,一共两帧数据,而在上一个状态已经传输了一帧,本状态传输最后一帧数据,所以需要判断trn_reof_n 帧结束信号,同样需要主、从设备都准备好,即trn_rsrc_rdy_n 和trn_rdst_rdy_n 同时有效才能传输。而在BMD128模式下,只需一帧数据就足够了。这可以从上面两个时序图中可以清晰看出来。) 下面比较下BMD64和BMD128的RX引擎中对几个状态机的定义。 先来看看BMD64: //接收引擎关键状态机的8个状态 `define BMD_64_RX_RST 8'b00000001//接收引擎复位状态 `define BMD_64_RX_MEM_RD32_QW1 8'b00000010//存储器读状态 `define BMD_64_RX_MEM_RD32_WT 8'b00000100//等待存储器读结束 `define BMD_64_RX_MEM_WR32_QW1 8'b00001000//存储器写状态 `define BMD_64_RX_MEM_WR32_WT 8'b00010000//等待存储器写结束 `define BMD_64_RX_CPL_QW1 8'b00100000//不带数据的完成 `define BMD_64_RX_CPLD_QW1 8'b01000000//带数据完成 `define BMD_64_RX_CPLD_QWN 8'b10000000//带数据完成 //接收引擎4种标头 `define BMD_MEM_RD32_FMT_TYPE 7'b00_00000//存储器读请求:TLP头大小为3个双字,不带数据 `define BMD_MEM_WR32_FMT_TYPE 7'b10_00000//存储器写请求:TLP头大小为3个双字,带数据 `define BMD_CPL_FMT_TYPE 7'b00_01010//完成报文:TLP头大小为3个双字,不带数据;包括存储器、配置和I/O写完成 `define BMD_CPLD_FMT_TYPE 7'b10_01010//带数据完成报文:TLP头大小为3个双字;包括存储器读、配置读、I/O读和原子读操作完成 先来看看BMD128: //定义了8种关键状态机状态 `define BMD_128_RX_RST 8'b00000001 `define BMD_128_RX_MEM_RD32_STRAD 8'b00000010 `define BMD_128_RX_MEM_RD32_WT 8'b00000100 `define BMD_128_RX_MEM_WR32_STRAD 8'b00001000 `define BMD_128_RX_MEM_WR32_WT 8'b00010000 `define BMD_128_RX_CPL_STRAD 8'b00100000 `define BMD_128_RX_CPLD_STRAD 8'b01000000 `define BMD_128_RX_CPLD_QWN 8'b10000000 //定义了4种标头 `define BMD_MEM_RD32_FMT_TYPE 7'b00_00000 `define BMD_MEM_WR32_FMT_TYPE 7'b10_00000 `define BMD_CPL_FMT_TYPE 7'b00_01010 `define BMD_CPLD_FMT_TYPE 7'b10_01010
  • 热度 21
    2015-9-7 21:30
    2712 次阅读|
    1 个评论
    1、 读操作(25Mhz)     该操作支持最高时钟速率为25Mhz的读操作。执行该操作时,芯片内部地址指针自动递增,连续输出从起始地址单元开始的数据,直到遇到CE#信号的上升沿。如果到达最高位的地址,地址指针返回最低位的地址继续递增。例如,SST25VF032B的地址最高位为0x3fffff,当内部地址指针到达0x3fffff时,下次将返回地址最低位0x0开始继续递增。     该操作对应8bits的命令为0x03,后面跟随24位的地址,高位先发。在连续的读操作执行过程中,CE#必须保持为低电平。具体时序请见图1。 图1读操作(25Mhz)时序 2、高速读操作(50MHz)     该操作支持最高时钟速率为50Mhz的读操作。执行该操作时,同读操作(25Mhz)模式,芯片内部地址指针自动递增,连续输出从起始地址单元开始的数据,直到遇到CE#信号的上升沿。如果到达最高位的地址,地址指针返回最低位的地址继续递增。例如,SST25VF032B的地址最高位为0x3fffff,当内部地址指针到达0x3fffff时,下次将返回地址最低位0x0开始继续递增。     该操作对应8bits的命令为0x0b,后面跟随24位的地址以及8位的填充位,高位先发。在填充位之后SO输出读出的数据。具体时序请见图2。 图2高速操作(50Mhz)时序 3、Byte编程操作     该操作每次向一个地址单元写一个字节的数据,每次写一个字节的数据前都要在SI总线上发送24位的地址数据。在向相应地址写数据前,需确保待写入的地址处于已擦除状态(0xff),同时需要进行写使能(WREN)操作。在该操作进行的过程中,CE#信号需要保持为低。      该操作对应8bits的命令为0x02,后面跟随24位的地址和8位的数据,高位先发。发送完成后,查询状态寄存器中的BUSY或等待T BP 时间(可在芯片手册中查询,SST25VF032B为10us),BUSY为0或等待T BP 时间结束后可执行下一步操作。具体时序请见图3。 图3 Byte编程操作时序 4、AAI(Auto Address Increment)word编程模式     AAI word编程模式允许只配置一次起始地址的情况下写入多个word的数据,一个word为2个字节。写入之前需确保待写入的地址处于已擦除状态(0xff)。     执行AAI编程模式前,必须执行写使能(WREN)操作。该操作对应8bits的命令为0xad,后面跟随24位的地址,然后是一个word的数据。一个word中第一个字节的数据写入{ , =0}的地址中,第二个字节写入{ , =1}的地址中。有3种方式可以判断AAI编程操作过程中每个word写入完成:     1)检测SO信号:需要在AAI word编程操作前执行EBSY(0x70)命令(如图4所示),使能SO作为忙状态信号,1为空闲,0为忙。结束AAI word编程操作后,需要执行DBSY(0x80)命令(如图5所示),去使能SO作为忙状态信号,本设计采用的就是这种方式; 图4 EBSY(0x70)命时序 图5 DBSY(0x70)命时序     2)读取状态寄存器中的BUSY位:通过发送WRSR(0x01)命令,读取状态寄存器,根据状态寄存器中的BUSY位判断;     3)等待T BP 时间。     根据以上条件判断芯片空闲时,后续0xad命令和2个字节的数据可以继续发送。最后一个字节的数据发送完成后,检测忙状态,空闲时发送WRDI(0x04)命令结束AAI word编程操作。     当完成最后一个未被写保护的地址单元的AAI word编程操作后,将退出AAI word编程模式,且复位状态寄存器中的WEL位(WEL=0)和AAI位(AAI=0)。     采用SO作为忙状态信号的AAI word编程操作时序如图6所示,采用读取状态寄存器中的BUSY位的AAI word编程操作时序如图7所示      图6 采用SO作为忙状态信号的AAI word编程操作时序 图7 采用读取状态寄存器中的BUSY位的AAI word编程操作时序 5、扇区(sector)擦除操作     扇区擦除操作擦除指定的4K字节大小的扇区,将值置为0xff。该操作对写保护的区域无效。扇区擦除操作之前,需要进行写使能操作(WREN)。     扇区擦除操作对应的8bits命令为0x20,后面跟随24位的地址,其中A23-A12用来确定擦除的扇区。扇区擦除操作完成后可以通过判断SO为空闲状态(需要先执行EBSY命令)和等待T SE 时间(在芯片手册中可查询)的方法来确定是否可执行下次操作。扇区擦除操作的时序如图8所示。       图8 扇区擦除操作时序 6、32K字节和64K字节的块擦除操作     32K字节和64K字节的块擦除操作分别擦除地址对应的32K字节和64K字节的块,将值置为0xff。该操作对写保护的区域无效。块擦除操作之前,需要进行写使能操作(WREN)。     32K字节块擦除操作对应的8bits命令为0x52,后面跟随24位的地址,其中A23-A15用来确定擦除的块;64K字节块擦除操作对应的8bits命令为0xd8,后面跟随24位的地址,其中A23-A16用来确定擦除的块。块擦除操作完成后可以通过判断SO为空闲状态(需要先执行EBSY命令)和等待T BE 时间(在芯片手册中可查询)的方法来确定是否可执行下次操作。32K字节块擦除操作的时序如图9所示,64K字节块擦除操作的时序如图10所示。 图9 32K字节块擦除操作时序 图10 64K字节块擦除操作时序 7、片擦除操作     片擦除操作擦整片flash所有地址的数据,将其置为0xff。该操作对写保护的区域无效。片擦除操作之前,需要进行写使能操作(WREN)。     该操作对应的8bits命令为0x60或0xc7,后面不需要跟随地址发送。片擦除操作完成后可以通过判断SO为空闲状态(需要先执行EBSY命令)和等待T CE 时间(在芯片手册中可查询)的方法来确定是否可执行下次操作。片擦除操作的时序如图11所示。 图11 片擦除操作时序 8、读状态寄存器操作(RDSR)     读状态寄存器操作可在在任何时刻执行,包括写和擦除操作进行的间隔。在写操作进行的间隔,通过读状态寄存器的BUSY位可以获知写操作的完成情况。     读状态寄存器操作对应的8bits命令为0x05,在命令发送完成后下个时钟下降沿开始输出状态寄存器数据。读状态寄存器操作的时序如图12所示。 图12 读状态寄存器操作时序 9、写使能操作(WREN)     写使能操作将状态寄存器中的WREN位置为1,表示写和擦除操作可进行。在任何写(包括写状态寄存器)和擦除操作之前都必须执行写使能操作,因为执行完任何写(包括写状态寄存器)和擦除操作之后,状态寄存器中的WREN位都会在CE#的上升沿被置0。写使能操作对应的8bits命令为0x06。写使能操作的时序如图13所示。 图13 写使能操作时序 10、写去使能操作(WRDI)     写去使能操作将状态寄存器中的WREN位和AAI位都置为0。写去使能操作无法终止任何擦除操作,任何擦除操作都必须等待T SP /T BP /T CP 时间完成。写去使能操作对应的8bits命令为0x04。写去使能操作的时序如图14所示。 图14 写去使能操作时序 11、使能写状态寄存器操作(EWSR)和写状态寄存器操作(WRSR)      使能写状态寄存器操作使能状态寄存器的写权限,写状态寄存器前必须先使能写状态寄存器,防止对状态寄存器的误操作。使能写状态寄存器操作对应的8bits命令为0x50或0x06,。     写状态寄存器操作可以改变状态寄存器中的BP3-BP0、BPL位。WP#管脚为0时,写状态寄存器操作无效,WP#管脚为1时,需要将BPL置为1,才能写BP3-BP0。写状态寄存器操作对应的8bits命令为0x01。使能写状态寄存器操作和写状态寄存器操作的时序如图15所示。 图15 使能写状态寄存器操作和写状态寄存器操作的时序 12、读ID操作(RDID)和JEDEC读ID操作     读ID操作(RDID)和JEDEC读ID操作用来读取芯片信息,暂不详述,具体请参见芯片手册。   下一篇将讲解实现各项操作的状态机,真正有料了要来了哦!
  • 热度 19
    2015-6-18 18:28
    1827 次阅读|
    0 个评论
    一,概述 用Altera的话来讲,timequest timing analyzer是一个功能强大的,ASIC-style的时序分析工具。采用工业标准--SDC(synopsys design contraints)--的约束、分析和报告方法来验证你的设计是否满足时序设计的要求。在用户的角度,从我使用TimeQuest的经验看,它与IC设计中经常用到的比如prime time,time craft等STA软件是比较类似的。用过prime time或time craft的朋友是非常容易上手的。 在这一系列的文章里,我将会拿一个DAC7512控制器的verilog设计作为例子,详细讲解如何使用TimeQuest进行时序设计和分析。 二,TimeQuest的基本操作流程 做为altera FPGA开发流程中的一个组成部分,TimeQuest执行从验证约束到时序仿真的所有工作。Altera推荐使用下面的流程来完成TimeQuest的操作。 1. 建立项目并加入相关设计文件      不管做什么事情,都需要有一个目标或者说对象。我们用TimeQuest做时序分析,当然也需要一个对象,这个对象实际上就是我们的设计。所以首先是要建立一个Quartus II的项目,并把所有需要的设计文件都加入到项目中去。需要注意的一点是,这里的设计文件,不仅仅包含逻辑设计相关的文件,也包含已经存在的时序约束文件,当然,需要以synopsys Design Constraints(.sdc)的格式存在的。 2. 对项目进行预编译(initial compilation)     项目建立以后,如果从来没有对项目进行过编译的话,就需要对项目进行预编译。这里的预编译是对应于全编译(full compilation)来讲的,我们可以理解为预编译是对项目进行部分的编译,而全编译是对项目进行完整的编译。做预编译的目的是为了生成一个initial design database,然后我们可以根据这个database用Timequest采用交互的模式生成时序约束。实际上,对于小的设计,编译时间并不是很长的话,完全可以不去区分预编译和全编译,需要编译的时候,直接做全编译就可以了,做全编译的话,可以生成一个post-fit的database,完全可以给TimeQuest使用。 3. 向设计中添加时序约束      在用TimeQuest做时序分析之前,必须要指定出对时序的要求,也就是我们通常所说的时序约束。这些约束包括时钟,时序例外(timing exceptions)和输入/输出延时等。     默认情况下,Quartus II 软件会给所有没有被下约束的时钟都设定为1GHz。没有任何的时序例外,也就是说所有的timing path都按1T去check。所有的输入/输出的延迟都按0来计算。这显然不符合绝大多数设计的时序要求,所以有必要根据设计的特性,添加必要的时序约束。     如上所述,时序约束主要包括三类:时钟,时序例外和输入/输出延迟。其中时钟和输入/输出延迟可以认为是在某种程度上增强时序设计的要求。而时序例外可以认为是在某种程度上降低时序设计的要求。比如说,仅仅设定一个时钟的频率为100MHz的话,这个时钟域里所有timing path都需要能工作在100MHz下。这显然是增强了时序设计的要求。可是如果在这个时钟域下面,有部分timing path是不需要做1T的check的,那么就可以通过添加时序例外来避免对这些timing path做1T的check,即降低了时序设计的要求。     在用TimeQuest做时序分析时,如果非常熟悉设计的构架和对时序的要求,又比较熟悉sdc的相关命令,那么可以直接在sdc文件里输入时序约束的命令。而通常情况下,可以利用TimeQuest GUI提供的设定时序约束的向导添加时序约束。不过要注意的是,用向导生成的时序约束,并不会被直接写到sdc文件里,所以如果要保存这些时序约束,必须在TimeQuest用write sdc的命令来保存所生成的时序约束。 4. 执行完整的编译     在设定好时序约束以后,就需要对整个设计进行完整的编译。在编译过程中,软件会优化设计的逻辑、布局布线等来尽可能满足所有的时序约束。     如果没有添加时序约束,那么软件在编译的时候,会按照默认的时序约束对设计进行优化,对于绝大多数的设计,都会报出来时序的问题,但因为默认的时序约束与设计本身的要求在绝大多数情况下,都是不同的,所以这些时序的问题也并不是设计本身的问题,并没有太多的参考价值,而且很多初学者也不会注意到这个问题。这样就把设计中很多潜在的时序问题给隐藏起来了,最终带来的可能就是系统运行的不稳定,甚至是完全不能运行。 5. 验证时序     当完成编译以后,我们就可以用TimeQuest来验证时序了。在时序分析的过程中,TimeQuest会分析设计中所有的timing path,计算每一条timing path的延时,检查每一条timing path是否满足时序约束,最后按照positive slack或negative slack来报告时序分析的结果。其中negative slack就表示对应的timing path不满足时序约束的要求(timing violation)。     如果遇到有不满足时序要求的情况,则可以根据对应的时序报告分析设计,确定如何优化设计使之满足时序约束。时序约束有任何变化的话,都需要重新编译设计。这个反复的过程可以让我们解决设计中的时序问题。 三,DAC7512控制器     DAC7512是一个具有三线串行接口的DAC。我们基于FPGA用Verilog语言实现了一个简单的DAC7512的控制器。下面是控制器的结构图:     DAC7512控制器由三个模块组成,PLL用来生成控制器所要的时钟C0(25MHz)和C1(50MHz),其lock信号用来做为控制器的异步reset。da_data模块生成要送往DAC7512的数据,其中DA_DATA为数据,DA_DATA_EN为数据有效信号,该模块使用C0时钟,整个属于C0时钟域。DAC7512模块用于将DA_DATA转换成符合DAC7512接口标准的串行数据并送给DAC7512,要用到C1(50MHz)和DA_SCLK(C1二分频,25MHz)两个时钟。     DAC7512控制器一共有四个输入输出端口。CLK_IN为PLL的基准时钟,为25MHz。DA_DIN,DA_SCLK和DA_SYNC为三线串口,都为输出端口。     由于C0,C1是由同一个PLL输出的,DA_SCLK是由C1经二分频得到的,三者之间是同步的,处于同一个clock group中。     DAC7512模块的详细设计资料可参照本博客中 “FPGA设计中DAC7512控制的Verilog实现” 的文章。不过要注意一点的是,在串行总线上,DA_DIN是在DA_SCLK的下降沿有效的。把DA_DIN设计为C1时钟域的信号,并控制其值只在DA_SCLK为高电平的时候发生变化。这样可以把DA_DIN与DA_SCLK之间的时序要求转换为DA_DIN在C1时钟域的时序要求,细节我们会在下面介绍。
  • 热度 21
    2015-6-1 14:46
    1194 次阅读|
    1 个评论
    操作时序永远使用是任何一片IC芯片的最主要的内容。一个芯片的所有使用细节都会在它的官方器件手册上包含。所以使用一个器件事情,要充分做好的第一件事就是要把它的器件手册上有用的内容提取,掌握。介于中国目前的芯片设计能力有限,所以大部分的器件都是外国几个IC巨头比如TI、AT、MAXIM这些公司生产的,器件资料自然也是英文的多,所以,英文的基础要在阅读这些数据手册时得到提高哦。即便有中文翻译版本,还是建议看英文原版,看不懂时不妨再参考中文版,这样比较利于提高。 我们首先来看1602的引脚定义,1602的引脚是很整齐的SIP单列直插封装,所以器件手册只给出了引脚的功能数据表: 我们只需要关注以下几个管脚: 3脚:VL,液晶显示偏压信号,用于调整LCD1602的显示对比度,一般会外接电位器用以调整偏压信号,注意此脚电压为0时可以得到最强的对比度。 4脚:RS,数据/命令选择端,当此脚为高电平时,可以对1602进行数据字节的传输操作,而此脚为低电平时,则是进行命令字节的传输操作。命令字节,即是用来对LCD1602的一些工作方式作设置的字节;数据字节,即使用以在1602上显示的字节。值得一提的是,LCD1602的数据是8位的。 5脚:R/W,读写选择端。当此脚为高电平可对LCD1602进行读数据操作,反之进行写数据操作。笔者认为,此脚其实用处不大,直接接地永久置为低电平也不会影响其正常工作。但是尚未经过复杂系统验证,保留此意见。 6脚:E,使能信号,其实是LCD1602的数据控制时钟信号,利用该信号的上升沿实现对LCD1602的数据传输。 7~14脚:8位并行数据口,使得对LCD1602的数据读写大为方便。 现在来看LCD1602的操作时序: 在此,我们可以先不读出它的数据的状态或者数据本身。所以只需要看两个写时序: ① 当我们要写指令字,设置LCD1602的工作方式时:需要把RS置为低电平,RW置为低电平,然后将数据送到数据口D0~D7,最后E引脚一个高脉冲将数据写入。 ② 当我们要写入数据字,在1602上实现显示时:需要把RS置为高电平,RW置为低电平,然后将数据送到数据口D0~D7,最后E引脚一个高脉冲将数据写入。 发现了么,写指令和写数据,差别仅仅在于RS的电平不一样而已。以下是LCD1602的时序图: 大家要慢慢学会看时序图,要知道操作一个器件的精华便蕴藏在其中,看懂看准了时序,你操控这个芯片就是非常容易的事了。1602的时序是我见过的一个最简单的时序: 1、注意时间轴,如果没有标明(其实大部分也都是不标明的),那么从左往右的方向为时间正向轴,即时间在增长。 2、上图框出并注明了看懂此图的一些常识: (1).时序图最左边一般是某一根引脚的标识,表示此行图线体现该引脚的变化,上图分别标明了RS、R/W、E、DB0~DB7四类引脚的时序变化。 (2).有线交叉状的部分,表示电平在变化,如上所标注。 (3).应该比较容易理解,如上图右上角所示,两条平行线分别对应高低电平,也正好吻合(2)中电平变化的说法。 (4).上图下,密封的菱形部分,注意要密封,表示数据有效,Valid Data这个词也显示了这点。 3、需要十分严重注意的是,时序图里各个引脚的电平变化,基于的时间轴是一致的。一定要严格按照时间轴的增长方向来精确地观察时序图。要让器件严格的遵守时序图的变化。在类似于18B20这样的单总线器件对此要求尤为严格。 4、以上几点,并不是LCD1602的时序图所特有的,绝大部分的时序图都遵循着这样的一般规则,所以大家要慢慢的习惯于这样的规则。 也许你还注意到了上面有许多关于时间的标注,这也是个十分重要的信息,这些时间的标注表明了某些状态所要维持的最短或最长时间。因为器件的工作速度也是有限的,一般都跟不上主控芯片的速度,所以它们直接之间要有时序配合。话说现在各种处理器的主频也是疯狂增长,日后搞不好出现个双核单片机也不一定就是梦话。下面是时序参数表: 大家要懂得估计主控芯片的指令时间,可以在官方数据手册上查到MCU的一些级别参数。比如我们现在用AVR M16做为主控芯片,外部12MHz晶振,指令周期就是一个时钟周期为(2/12MHz)s,所以至少确定了它执行一条指令的时间是us级别的。我们看到,以上给的时间参数全部是ns级别的,所以即便我们在程序里不加延时程序,也应该可以很好的配合LCD1602的时序要求了。怎么看这个表呢?很简单,我们在时序图里可以找到TR1,对应时序参数表,可以查到这个是E上升沿/下降沿时间,最大值为25ns,表示E引脚上的电平变化,必须在最大为25ns之内的时间完成。大家看是不是这个意思? 现在我来解读我对这个时序图的理解: 当要写命令字节的时候,时间由左往右,RS变为低电平,R/W变为低电平,注意看是RS的状态先变化完成。然后这时,DB0~DB7上数据进入有效阶段,接着E引脚有一个整脉冲的跳变,接着要维持时间最小值为tpw=400ns的E脉冲宽度。然后E引脚负跳变,RS电平变化,R/W电平变化。这样便是一个完整的LCD1602写命令的时序。 ps感谢热心网友的指出错误之处: (1/12MHz)s是振荡周期,而不是时钟周期,因为时钟周期(状态周期)等于两个振荡周期,换句话说就是对振动频率进行“二分频”的振荡信号,所以(2/12MHz)s才是晶振为12MHz时的时钟周期。 来源:21ic
相关资源