马老师,请问您书上的(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)
请马老师指点迷津啊,先谢谢了 书上的表我做过整理的,为了更清楚一点。
对于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就复杂了,上升沿/下降沿都有动作,而且还跟准备状态有关。如果不清楚,就非常容易出错。 对头,我以前也是这样,对准备状态 这个理解不足 明白了,马老师说的很清楚~o(∩_∩)o... mark 回复【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的话,那结果就错了
请马老师指点 回复【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; //产生上升沿,打入数据,同时也是返回准备状态,停留在高电平
} 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初始化得到的呢? mark 回复【1楼】machao
-----------------------------------------------------------------------
我在7楼的疑问 和 6楼的 差不多。 回复【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位根本没有打入! 回复【10楼】machao
-----------------------------------------------------------------------
马老师,我的意思是那样第一次循环后,byte <<=1;是左移了一位(但这一位并没有移入移位寄存器啊,丢失了),第二次循环时送入移位寄存器的位是byte的第二位(次高位),那么byte的最高位不就没有送入移位寄存器吗???这样就导致了一位数据的丢失 laotan 回复【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;
} good,我用PIC验证13楼的程序没问题。 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. 顶m&m. do mark
页:
[1]