guxingganyue 发表于 2010-10-29 21:23:20

马老师,请问您书上的(354页)的595真值表和下面的驱动函数,我对他有很大的疑问,请批评指点

1、您书中595的真值表中有下降沿,但有的pdf中怎么没有呢?---见下图

2、不管是下面的函数还是我改过后,595驱动的结果都一样,不知为什么。
void Hc595_send_byte(unsigned char byte)
{
   unsigned char i;
   for(i=0;i<8;i++)
   {
          if(byte&0x80)
               Hc595_data=1;
          else
               Hc595_data=0;
          byte <<=1;
          Hc595_clk=1;//下降沿
          Hc595_clk=0;   
   }
   Hc595_stcp=1;//下降沿
   Hc595_stcp=0;
}
改过后的
void Hc595_send_byte(unsigned char byte)
{
   unsigned char i;
   for(i=0;i<8;i++)
   {
          if(byte&0x80)
               Hc595_data=1;
          else
               Hc595_data=0;
          byte <<=1;
          Hc595_clk=0;//上降沿
          Hc595_clk=1;   
   }
   Hc595_stcp=0;//上降沿
   Hc595_stcp=1;
}


http://cache.amobbs.com/bbs_upload782111/files_34/ourdev_593853BGW391.jpg
(原文件名:33.jpg)

http://cache.amobbs.com/bbs_upload782111/files_34/ourdev_593854AA6FRQ.jpg
(原文件名:45.jpg)

http://cache.amobbs.com/bbs_upload782111/files_34/ourdev_593855WZFKBH.jpg
(原文件名:儿童.jpg)

http://cache.amobbs.com/bbs_upload782111/files_34/ourdev_593856B9LQ2U.jpg
(原文件名:595(philip).jpg)

请马老师指点迷津啊,先谢谢了

machao 发表于 2010-10-30 00:07:19

书上的表我做过整理的,为了更清楚一点。

对于595,不管是CLK,还是LATCH,都是上升沿起作用的,下降沿没有动作。

另外的考虑是CLK和LATCH的准备状态(起始/结束)的电平,由于595只是上升沿有动作,所以准备状态为高或低电平都可以。但我建议为低电平,这样第1次改变电平状态就意味这操作,操作完后,拉到低电平,保持。如果准备状态是高电平,那么是在第2次改变电平才操作。

你的两段代码都能正确的操作595,区别在2点:
void Hc595_send_byte(unsigned char byte)
{
   unsigned char i;
   for(i=0;i<8;i++)
   {
          if(byte&0x80)
               Hc595_data=1;
          else
               Hc595_data=0;
          byte <<=1;
          Hc595_clk=1;   //下降沿(这个解释不对!)===》 产生上升沿,打入数据
          Hc595_clk=0;   //                        ===》 产生下降沿,回到准备状态,停留在低电平   
   }
   Hc595_STCp=1;       //下降沿XX                ===》 产生上升沿,锁存数据
   Hc595_STCp=0;       //                        ===》 产生下降沿,回到准备状态,停留在低电平

void Hc595_send_byte(unsigned char byte)
{
   unsigned char i;
   for(i=0;i<8;i++)
   {
          if(byte&0x80)
               Hc595_data=1;
          else
               Hc595_data=0;
          byte <<=1;
          Hc595_clk=0;   //xx上降沿            //产生下降沿,无用
          Hc595_clk=1;                         //产生上升沿,打入数据,同时也是返回准备状态,停留在高电平
   }
   Hc595_STCp=0;       //xx上降沿            //产生下降沿,无用
   Hc595_STCp=1;                           //产生上升沿,打入数据,同时也是返回准备状态,停留在高电平
}

对于串行通信,CLK的准备状态是什么,上升沿/下降沿做什么,都是非常重要的,思路要非常清晰。595属于比较简单的,只有上升沿有作用。而SPI就复杂了,上升沿/下降沿都有动作,而且还跟准备状态有关。如果不清楚,就非常容易出错。

skynet 发表于 2010-10-30 08:27:45

对头,我以前也是这样,对准备状态 这个理解不足

lyr0710 发表于 2010-10-30 19:01:28

明白了,马老师说的很清楚~o(∩_∩)o...

xtaens 发表于 2010-10-30 19:07:25

mark

guxingganyue 发表于 2010-10-30 19:48:14

回复【1楼】machao
-----------------------------------------------------------------------

马老师这么晚了还在回帖,您太辛苦了。经过您的讲解,我终于明白了,再次感谢一下!!!

再请教一个问题:

您书上写的是
void Hc595_send_byte(unsigned char byte)
{
   unsigned char i;
   for(i=0;i<=7;i++)
   {   
          Hc595_data=byte&1<<i;   
          Hc595_clk=1;   
          Hc595_clk=0;      
   }
}
其中:Hc595_data=byte&1<<i;Hc595_data的值应该为0或1,但我在ICCavr6.31a中这样写,结果是错的, 即用函数Hc595_send_byte(unsigned char byte);发送的字符时发出的编码不正确,我改成
if(byte&0x80)
       Hc595_data=1;
else   
       Hc595_data=0;
就对了。

例如:Hc595_data=0x40&0x50,Hc595_data=1;呢还是Hc595_data=0x40呢,假如Hc595_data=0x40的话,那结果就错了

请马老师指点

guxingganyue 发表于 2010-10-30 20:43:53

回复【1楼】machao
-----------------------------------------------------------------------

马老师,我还有一个疑问:
初始化时:

Hc595_clk=1;
Hc595_STCp=1;

执行下面的函数后,在第一个for循环中并没有上升沿产生,所以byte的最高位没有被送入锁存器里,所以一位数据已经丢失了
我这样理解对吗???

我按这样的写法把程序下进去后刚上电时总是有led不亮,而等会儿就正常了

void Hc595_send_byte(unsigned char byte)
{
   unsigned char i;
   for(i=0;i<8;i++)
   {
          if(byte&0x80)
               Hc595_data=1;
          else   
               Hc595_data=0;
          byte <<=1;
          Hc595_clk=1;   //xx上降沿            //产生下降沿,无用
          Hc595_clk=0;                         //产生上升沿,打入数据,同时也是返回准备状态,停留在高电平
   }
   Hc595_STCp=1;       //xx上降沿            //产生下降沿,无用
   Hc595_STCp=0;                           //产生上升沿,打入数据,同时也是返回准备状态,停留在高电平
}

scort 发表于 2010-10-30 20:54:28

1楼的回答我也有点不懂得地方,希望马老师帮忙解答,谢谢。
Hc595_clk=1;   //下降沿(这个解释不对!)===》 产生上升沿,打入数据
Hc595_clk=0;   //                        ===》 产生下降沿,回到准备状态,停留在低电平

这个默认就是认为准备状态的电平是0(Hc595_clk=0)这样才能产生上升沿。Hc595_clk=0;是如何得来? 假设接的是51单片机IO端口,默认的话 Hc595_clk=1 啊? 不是很明白,这个内容是十二章的,没看见有初始化。望解答。

Hc595_clk=0;   //xx上降沿            //产生下降沿,无用
Hc595_clk=1;                         //产生上升沿,打入数据,同时也是返回准备状态,停留在高电平

这个默认就是认为准备状态电平是1(Hc595_clk=1)这样才能产生下降升沿,无用。Hc595_clk=1;是如何得来得?
是不是51单片机或avr初始化得到的呢?

tangwei039 发表于 2010-10-30 20:56:44

mark

scort 发表于 2010-10-30 21:07:42

回复【1楼】machao
-----------------------------------------------------------------------

我在7楼的疑问 和 6楼的 差不多。

machao 发表于 2010-11-1 00:35:54

回复【6楼】guxingganyue ,【7楼】 scort

请仔细、全面、踏实的学习。代码只是参考,不同的环境下需要做修改的。

我用的是CVAVR,这个C支持位(bit)变量的。代码中的Hc595_clk、Hc595_data都是位变量。ICC不支持位变量,你这样写有问题的。


在初始化时,当然应该把CLK和stcp设置在准备状态。

下面是六楼有问题的代码(不知道6楼是否仔细看了我在1楼的代码解释,6楼的解释怎么还是反的!)

Hc595_clk=1;   
Hc595_STCp=1;   
// 以上是初始化,把2个信号的准备状态定在高电平

void Hc595_send_byte(unsigned char byte)   
{   
   unsigned char i;   
   for(i=0;i<8;i++)   
   {   
          if(byte&0x80)   
               Hc595_data=1;   
          else   
               Hc595_data=0;   
          byte <<=1;   
          Hc595_clk=1;   //xx上降沿            //产生下降沿,无用 ???
          Hc595_clk=0;                         //产生上升沿,打入数据,同时也是返回准备状态,停留在高电平???
   }   
   Hc595_STCp=1;       //xx上降沿            //产生下降沿,无用???
   Hc595_STCp=0;                           //产生上升沿,打入数据,同时也是返回准备状态,停留在高电平 ???
}   

   //那么在第一次循环中没有产生上升沿,只有一个下降沿。这意味者第1位根本没有打入!

guxingganyue 发表于 2010-11-1 15:52:47

回复【10楼】machao
-----------------------------------------------------------------------

马老师,我的意思是那样第一次循环后,byte <<=1;是左移了一位(但这一位并没有移入移位寄存器啊,丢失了),第二次循环时送入移位寄存器的位是byte的第二位(次高位),那么byte的最高位不就没有送入移位寄存器吗???这样就导致了一位数据的丢失

All-Star 发表于 2010-11-1 18:38:36

laotan

guxingganyue 发表于 2010-11-1 19:43:22

回复【10楼】machao
-----------------------------------------------------------------------
马老师,我认为这样写也不是什么错误,只能说明我的595程序写的不够健壮,初始化函数应该不要求唯一的写法

Hc595_clk=1;   
Hc595_STCp=1;   
// 以上是初始化,把2个信号的准备状态定在高电平

void Hc595_send_byte(unsigned char byte)   
{   
   unsigned char i;   
   for(i=0;i<8;i++)   
   {   
          if(byte&0x80)   
               Hc595_data=1;   
          else   
               Hc595_data=0;   
          byte <<=1;   
          Hc595_clk=1;   //xx上降沿            //产生下降沿,无用 ???
          Hc595_clk=0;                         //产生上升沿,打入数据,同时也是返回准备状态,停留在高电平???   
   }   
   Hc595_STCp=1;       //xx上降沿            //产生下降沿,无用???
   Hc595_STCp=0;                           //产生上升沿,打入数据,同时也是返回准备状态,停留在高电平 ???
}   



可以改为

Hc595_clk=1;   
Hc595_STCp=1;   
// 以上是初始化,把2个信号的准备状态定在高电平

void Hc595_send_byte(unsigned char byte)   
{   
   unsigned char i;   
   for(i=0;i<8;i++)   
   {   
          if(byte&0x80)   
               Hc595_data=1;   
          else   
               Hc595_data=0;   
          byte <<=1;
          Hc595_clk=0;    //写成这样的话无论怎么初始化都应该没问题的
          Hc595_clk=1;
          Hc595_clk=0;                        
   }
   Hc595_STCp=0;    //写成这样的话无论怎么初始化都应该没问题的
   Hc595_STCp=1;               
   Hc595_STCp=0;         
}

xifengxia 发表于 2011-10-7 22:31:54

good,我用PIC验证13楼的程序没问题。

millwood0 发表于 2011-10-7 23:10:48

this is what I typically do:


void Hc595_send_byte(unsigned char byte)   
{   
   unsigned char i;   
   for(i=0;i<8;i++)   
   {   
          Hc595_clk=0;    //写成这样的话无论怎么初始化都应该没问题的
          if(byte&0x80)   
               Hc595_data=1;   
          else      
               Hc595_data=0;   
          Hc595_clk=1;   
          //Hc595_clk=0;                        
          byte <<=1;
   }   
   //Hc595_STCp=0;    //写成这样的话无论怎么初始化都应该没问题的
   //Hc595_STCp=1;               
   //Hc595_STCp=0;         
}   

it has the advantage of 1) requires no initialization; and 2) produces near 50% dc on clk, and 3) you can handle STCp separately - useful for multi-byte writes and can be easily replaced with a hardware spi routine.

mzbhy 发表于 2011-10-7 23:25:49

顶m&m.

jacky82512 发表于 2011-11-15 13:12:02

do mark
页: [1]
查看完整版本: 马老师,请问您书上的(354页)的595真值表和下面的驱动函数,我对他有很大的疑问,请批评指点