mawei 发表于 2010-12-29 23:24:36

问个菜鸟问题,马老师的书187页.关于把一字节数据由低到高输出到hc164上.

看书自学avr买了开发板觉得挺有兴趣的,在187页遇到了一个搞不懂的问题.

程序运行成功了但是有个疑问总也想不明白,请明白人指点一下吧.
不相关的我就省略了.


#define HC164_data PORTA.0
#define HC164_clk PORTA.1

void HC164_send_byte(char byte)//定义函数 吧一个字节的数据串行发送到74hc164 程序运行成功了.
{
    char i;
    for(i=0;i<=7;i++)
    {
      HC164_data=byte&1<<i;
      HC164_clk=1;
      HC164_clk=0;               
    }
}


HC164_data=byte&1<<i;   这句有些搞不懂假设byte=0xff i=0-7的话那么HC164_data 应该分别 为00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000我真的是刚入门的我都不知道我算的对不对,如果正确的话.PORTA.0每次只有2种状态但是00000001是八位的.就这个地方想不明白了.我想把所有的程序都理解了在往下做实验.知道的请指点下.多谢!

machao 发表于 2010-12-30 03:42:46

先学习或复习C语言的基本知识,回答下面的问题:

for(i=0;i<=7;i++)
{
   if (0x5a & 1<<i)
   {
         语句1;
      }
      else
      {
          语句2;
       }
}

在这个循环中,语句1执行几次?语句2执行几次?这2个语句分别在什么条件时执行的?


      i         执行(1 or 2)?
---------------------------
      0         语句?
      1         语句?
      2         语句?
      3         语句?   
      4         语句?
      5         语句?
      6         语句?
      7         语句?

millwood0 发表于 2010-12-30 06:50:20

there are multiple issues with the code:

1) using (1<<i) isn't very efficient. using a mask (i=0x01) for example, would speed up the speed considerably;
2) if you read hc164's data sheet, the data is shifted in on the rising edge of sck.

"HC164_data=byte&1<<i;   这句有些搞不懂假设byte=0xff i=0-7的话那么HC164_data 应该分别 为00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000 "

since the code is to shift the least significant bit first, as i starts from 0 (contrary to the spi protocol), the first bit in is byte's least significant bit (0th bit).

if you still want to shift the least significant bit, I would suggest that you rewrite it as follows:

void HC164_send_byte(unsigned char byte)//定义函数 吧一个字节的数据串行发送到74hc164 程序运行成功了.
{
    unsigned char i=0x01; //shift out the least significant bit first
    //for(i=0;i<=7;i++)
    do
    {
      HC164_clk=0;                //clear clk
      HC164_data=byte&i;          //set sdi
      HC164_clk=1;                //set clk -> strobe data out on the rising edge
      i = i << 1;               //send the next bit
    } while (i);                  //wait until all bits are sent
}

hope it helps.

mawei 发表于 2010-12-30 13:45:50

多些马老师和millwood0 的解答。

看来我对基础知识的掌握存在不少问题。
先答题。

循环中if (0x5a & 1<<i) 如果表达式的值为真执行 语句1 否者执行 语句2
0x5a 二进制 01011010
那么按位跟1进行与操作的结果中有4次返回非0的值(我一直以为1才是真,原来非0才是真)。
语句1执行4次,语句2执行4次。

i         执行(1 or 2)?
---------------------------
      0         语句2
      1         语句1
      2         语句2
      3         语句1   
      4         语句1   
      5         语句2
      6         语句1
      7         语句2

不知道我回答的对么。

然后到这里我突然想到了。是不是在avr的c语言中PORTA.0=因为这个代表一个端口只有2种状态,那么等号后面的表达式也想if语句一样只返回真或者假的值而不是一个8位的数据.

PORTA.0=00010000 这时前面的数据被判断真或者假而不是具体的8位2进制数,因为一个端口只有2种状态。
PORTA=00010000   这个就代表8个端口的状态。

这些规则都是由头文件来定义的么?不知道我理解的对不对。

machao 发表于 2010-12-30 19:53:54

还是基础概念的问题。

在任何的程序设计语言中,判断语句的定义是:IF(逻辑表达式),其中逻辑表达式的值只可能为“1”或“0”。

在 if (0x5a & 1<<i)语句中,括号中看上去是数值表达式,不是逻辑表达式,但由于IF ()的规定,这个数值表达式的结果必须转换成逻辑值。

按规定,当数值表达式的值不为另,其转换成逻辑值为“1”,只有数值表达式的值为另,其转换成逻辑值为“0”。

这里隐含了一个数据类型转换的操作。这个在学习C语言中的表达式计算和赋值语句都会讲到的。是基本概念。

=========================================
在LZ位代码中:

HC164_data = byte&1<<i;

HC164_data是BIT型变量,在标准C中是没有这个类型变量的,它是CVAVR中扩展的。这个BIT型变量,相当逻辑变量,只能有2个值“0”/“1”。赋值号右面是数值表达式,其结果是数值型值,但要赋给BIT型变量,就需要进行类型转换。这个转换也是隐含的,规则同转换为逻辑值相同。

这种情况在许多地方会用到的,例如:

int a = 0xaa55;
char b;

b = a;

此时b的值是多少?

而执行 b = a >> 8;后,b的值有是多少?这条语句同b = a / 256;有什么区别?

不要认为结果相同就没有区别,如果具备汇编的概念,你就知道应该用哪个更好了。

直接面向硬件的程序员是特殊的程序员,使用的许多语句是高效率的,但对于普通程序员来讲是不容易理解的。

millwood0 发表于 2010-12-30 21:16:01

"循环中if (0x5a & 1<<i) 如果表达式的值为真执行 语句1 否者执行 语句2 "

that's a bad way of coding.

this is better:

"if (0x5a & (1 << i))": it uses the brackets to force the priority.

"PORTA.0=00010000 这时前面的数据被判断真或者假而不是具体的8位2进制数,因为一个端口只有2种状态。 "

that's a terrible way of coding, as PORTA.0's value is compiler dependent: as PORTA.0 is a bit, some compilers will take 00010000's last bit (a 0) and assigned it ito PORTA.0; other compilers will take 00010000 and treat it as one, and assigned a 1 to PORTA.0.

millwood0 发表于 2010-12-30 21:16:52

in general, you should avoid the use of bit variables - as they are generally not supported natively by the hardware - 8051 being the exception.

whenever possible, use a mask.

tangwei039 发表于 2010-12-30 21:57:53

马老师,敬礼!!!!!!!

easywater 发表于 2010-12-31 02:57:01

mark

mawei 发表于 2011-1-2 00:25:31

多谢马老师和millwood0 的热心解答.原来是这么基础性的问题.是我的底子太薄啦,我会继续努力的.

taocongrong 发表于 2011-12-14 23:22:18

页: [1]
查看完整版本: 问个菜鸟问题,马老师的书187页.关于把一字节数据由低到高输出到hc164上.