搜索
bottom↓
回复: 30

马老师 请教你164的问题?

[复制链接]

出0入0汤圆

发表于 2011-11-17 14:25:38 | 显示全部楼层 |阅读模式
我在IAR里按马老师的164弄个测试的东西。结果不行。

#define HC164_data PORTE_Bit7//PORTE_Bit7
#define HC164_clk  PORTE_Bit6//

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

在主程序这样用的
HC164_clk=0; //164 init

        //164 scan
        {
          temp=0xfe; //赋显示初值
          for(n=0;n<8;n++)
          {
          HC164_send_byte(temp); //写数据,送显示
          DelayNms(500);
          temp<<=1; //准备下一个显示数据
          //temp=temp|0x01; //最低位置1
          }
          HC164_send_byte(0xff); //关闭显示
          DelayNms(500);
        }
后来在网络上找个就可以了。

请马老师指教。难道是我哪里不对---

出0入0汤圆

 楼主| 发表于 2011-11-17 14:31:36 | 显示全部楼层

(原文件名:164.jpg)

出0入0汤圆

发表于 2011-11-17 14:39:34 | 显示全部楼层
没有买过马老师的书,看马老师的程序我记得是CVAVR的吧,支持单个位操作

    没用过IAR,不知道是否支持单个位操作的,如果不支持,看下是不是这个问题


    另外:记得前两天也有人问马老师164的问题……

出0入0汤圆

发表于 2011-11-17 14:41:51 | 显示全部楼层
这么简单的代码你自己都不能分析吗?

出0入0汤圆

发表于 2011-11-17 14:52:00 | 显示全部楼层
其实我认识LZ,就是让马老师编个   按键 单击 双击  程序的那位

出0入0汤圆

发表于 2011-11-17 15:02:23 | 显示全部楼层
你的图是不是有问题。

你这个是高电平把灯点亮啊。

出0入0汤圆

 楼主| 发表于 2011-11-17 15:12:28 | 显示全部楼层
回复【3楼】machao
-----------------------------------------------------------------------

我试着改了一晚上,该不通啊。所以才来了这里请教。我也很慎重的

出0入0汤圆

 楼主| 发表于 2011-11-17 15:14:19 | 显示全部楼层
回复【5楼】rising_sun
-----------------------------------------------------------------------

是的,

出0入0汤圆

 楼主| 发表于 2011-11-17 15:16:45 | 显示全部楼层
回复【4楼】ijlc1314 夜猫
-----------------------------------------------------------------------

我也看了哪些帖子,问的是C的问题,但是我实际试验的时候出了问题。

大侠好像把我记住了。罪过啊

出0入0汤圆

 楼主| 发表于 2011-11-17 15:49:32 | 显示全部楼层
HC164_data=byte & 1<<i;//machao  

经过测试这个有问题,在IAR里

            if (byte & 1<<i) //ok
            HC164_data = 1;
            else
            HC164_data = 0;

下面这个就可以。

这个是谁的错?

出0入0汤圆

发表于 2011-11-17 16:31:47 | 显示全部楼层
回复【8楼】jacky82512  
-----------------------------------------------------------------------

    大侠……要我折寿哦,我也是刚刚学的AVR来的,不过我用的是WinAVR

    建议你用书中使用的编译器吧。我觉得不要在编译器上花费太多时间。

出0入0汤圆

发表于 2011-11-17 16:32:40 | 显示全部楼层
回复【9楼】jacky82512  
-----------------------------------------------------------------------

       你自己的错,谁叫你自己不去了解好编译器的

出0入0汤圆

发表于 2011-11-17 16:38:54 | 显示全部楼层
if (byte & 1<<i)  

汗! 这个逻辑!

出0入0汤圆

 楼主| 发表于 2011-11-17 16:40:25 | 显示全部楼层
HC164_data=byte & 1<<i;//

马老师你在书中这样写,164是不运行的。

byte & 1<<i;//
这个值 ?

出0入0汤圆

发表于 2011-11-17 16:45:00 | 显示全部楼层
回复【13楼】jacky82512  
-----------------------------------------------------------------------

        


    byte & 1<<i  等于  ( byte & ( 1<<i ) )

   

    这个没问题吧,我觉得主要是   左值是 bit变量,而右值不是,根本就不匹配, 编译器不同,结果也就不同了

出0入0汤圆

发表于 2011-11-17 21:47:44 | 显示全部楼层
在标准C中,没有bit(位)型的变量。在CVAVR中,BIT型变量是扩展的。

对于其它的一些编译器,比如ICC、GCC(WINAVR)都不支持BIT变量的。我记得老的IAR也不支持位变量的(我在查查看)。

如果你现在使用的IAR支持BIT变量,那么应该看看他的使用手册,了解如何支持和操作的。

简单的方法就是在AVR STUDIO中软件模拟一下,

执行 HC164_data = byte & 1<< i语句,看对应的I/O口输出是否对,另外,在AVR STUDIO中,直接看该语句对于的汇编代码,也可以知道原因是什么。

出0入127汤圆

发表于 2011-11-17 22:16:34 | 显示全部楼层
回复【1楼】jacky82512
-----------------------------------------------------------------------

照你这个图,如果164接的是5V,怎么可能亮灯?

出0入0汤圆

发表于 2011-11-17 22:34:41 | 显示全部楼层
1楼的图LED是会亮的,不过是164输出1点亮。LZ的硬件也太哪个了吧。

出0入0汤圆

 楼主| 发表于 2011-11-18 08:27:19 | 显示全部楼层
回复【17楼】machao
-----------------------------------------------------------------------

这个我已经注意到了。误以为那一极接5V了,结果是接地的。不好意思

出0入0汤圆

 楼主| 发表于 2011-11-18 09:19:51 | 显示全部楼层
弄不明白 怎么控制164从高到低  怎么从低到高  

            if (byte & 1<<i) //ok
            HC164_data = 1;  
            else  
            HC164_data = 0;
这样是从高到低 但是为什么是这样呢?

比如BYTE=0B1010 1010
i=0  是0000 0001 位与byte HC164_data是0
最低位先给HC164_data
那为什么还是从高到低呢?不大理解

请高手点明。

出0入0汤圆

发表于 2011-11-18 10:06:17 | 显示全部楼层
"for(i=0;i<=7;i++)  
    {  
        HC164_data=byte & 1<<i;//machao  
         
        //if (byte & 1<<i)  
        //HC164_data = 1;  
        //else  
        //HC164_data = 0; "

that particular piece of code is not spi-compliant as it sends lsb first and msb last.

also "HC164_data=byte & 1<<i;//machao  " also is poorly coded.

出0入0汤圆

 楼主| 发表于 2011-11-18 10:54:38 | 显示全部楼层
回复【20楼】millwood0
-----------------------------------------------------------------------

我e文好差,基本不能看懂。得有道翻译,翻译结果也都差强人意。
还是多谢了。millwood0

出0入0汤圆

发表于 2011-11-18 13:11:18 | 显示全部楼层
hc164不是标准的SPI接口,这个代码只是通过I/O口的模拟吧一个字节串出打入到HC164中,与SPI无关。

至于高位在前还是地位在前,这个都不是重要的,看你硬件的连接和实际的需要,只是简单的调整一下代码就可以了,这个没有什么死规定,是根据实际情况定的。关键是你是否掌握使用串行方式扩展成并行输出。

至于"HC164_data=byte & 1<<i; " 是否为“poorly coded”不是主要的,
难道“HC164_data = byte & (1<<i);就不是“poorly coded”啦,其实这句和上句是一样的。

关键是你是否掌握这句语句的作用。这个是你C语言掌握的水平问题。况且HC164_data=byte & 1<<i并不是什么非常难掌握和理解的语句。

你写的语句标准,可读性好只是锦上添花,真正的关键是你是否掌握思路和方法。

出0入0汤圆

 楼主| 发表于 2011-11-18 16:37:38 | 显示全部楼层
谢马老师。还是想搞明白。19楼的问题。是不是和164的逻辑结构有关系呢?
还是软件控制的?

比如BYTE=0B1010 1010
i=0  是0000 0001 位与byte HC164_data是0
最低位先给HC164_data
那为什么还是从高到低呢?不大理解

出0入0汤圆

发表于 2011-11-18 21:43:37 | 显示全部楼层
假定你1楼的图接线是164的D7接LED的D0,164的D0接LED的D7,8根连接反一下,程序应该如何变化?

出0入0汤圆

发表于 2011-11-18 21:46:00 | 显示全部楼层
现在的人更加是聪明了,还是笨了?搞不懂。这么一个小的变化都转不来。我已经解释的非常清楚了。

出0入0汤圆

发表于 2011-11-18 21:55:31 | 显示全部楼层
"比如BYTE=0B1010 1010  "

it sends the lowest bit first - when it works.

so in this case, you send 0b1010 1010 (0xaa) and get 0b0101 0101 (0x55) on hc164.

出0入0汤圆

发表于 2011-11-18 21:59:20 | 显示全部楼层
here is a quick exercise that I did.

=============example================

#include <ioavr.h>                                                                        //we use iar avr
//hardware configuration
#define HC164_PORT                PORTE
#define HC164_DDR                DDRE
#define HC164_CLK                (1<<0)
#define HC164_MOSI                (1<<1)

#define HC164_CLK_PIN        PORTE_Bit0
#define HC164_MOSI_PIN        PORTE_Bit1
//end hardware configuration

void hc164_init(void) {
        HC164_PORT &=~(HC164_CLK | HC164_MOSI);                        //clear clk/mosi
        HC164_DDR |= (HC164_CLK | HC164_MOSI);                        //clk / mosi as output
}

void hc164_write(unsigned char dat) {
        unsigned char mask = 0x80;                                                //mask, msb first
       
        //HC164_PORT &=~(HC164_CLK | HC164_MOSI);                        //clear clk/mosi
        //HC164_DDR |= (HC164_CLK | HC164_MOSI);                        //clk / mosi as output

        do {
                HC164_PORT &=~HC164_CLK;                                        //clear clk
                if (dat & mask) HC164_PORT |= HC164_MOSI;        //send 1
                else HC164_PORT &=~HC164_MOSI;                                //send 0
                HC164_PORT |= HC164_CLK;                                        //set clk
                mask = mask >> 1;                                                        //send the next bit
        } while (mask);                                                                        //send all bits
        //HC164_PORT &=~HC164_CLK;                                                //reset clk - optional
}

void hc164_write2(unsigned char dat) {
        unsigned char i;
       
        for (i=0; i<8; i++) {
                //HC164_MOSI_PIN = dat & (1<<i);                                        //send bits
                HC164_MOSI_PIN = (dat & (1<<i))? 1: 0;
                HC164_CLK_PIN=1;                                                        //send clock
                HC164_CLK_PIN=0;                                                        //clear clock
        }
}

int main( void )
{
        hc164_init();                                                                        //reset the hc164


        //send 1st byte
        HC164_PORT |= HC164_MOSI;                                                //indicates the start of the transmission
        hc164_write(0xaa);                                                                //send a byte
        HC164_PORT |= HC164_MOSI;                                                //indicates the end of the transmission

        //send 2nd byte
        HC164_PORT &=~HC164_MOSI;                                                //indicates the start of the transmission
        hc164_write2(0xaa);                                                                //send a byte
        HC164_PORT &=~HC164_MOSI;                                                //indicates the end of the transmission

        while (1) {
        }
        return 0;
}

=========================

the above code implements two hc164 write routines, hc164_write() and hc164_write2().

hc164_write() uses masks and sends the most significant bit first, consistent with the spi standard.

hc164_write2() is your implementation - it uses a for () loop, and bit shifts and sends the least significant bit first.
  *****notice that change I did in the particular implementation and I will come back there**********************

the hc164_write() sends the byte (0xaa) in 135us, and the bits show up correctly on hc164 (as 0xaa).

the hc164_write2() sends the byte (0xaa) in 470us, and the bits show up incorrectly on hc164 (as 0x55).



(原文件名:avr hc164.PNG)

出0入0汤圆

发表于 2011-11-18 22:05:48 | 显示全部楼层
here is the change I did in your hc164_write2() routine:

"                //HC164_MOSI_PIN = dat & (1<<i);                                        //send bits
                HC164_MOSI_PIN = (dat & (1<<i))? 1: 0;"

"HC164_MOSI_PIN = dat & (1<<i);" does not work under iar ewavr. C does not define bit operations. as such its implementation is uncertain and compiler dependent. "HC164_MOSI_PIN = dat & (1<<i);" for example works for gcc avr but not iar avr.

the correct implementation is to test (dat & (1<<i)) explicitly and then assign 1 or 0 to your output pin based on the test, as I did there.

a fancier implementation of this, which works on all C89 compilers, is "HC164_MOSI_PIN = !(!(dat & (1<<i)));"

出0入0汤圆

发表于 2011-11-18 22:07:19 | 显示全部楼层
the point here is that a) you  have to write code as much portable / readable and standard-compliant as you can; and b) try to rely as little on compiler extensions as you can.

that means don't use bit variables and use masks as much as you can.

出0入0汤圆

发表于 2011-11-18 22:10:21 | 显示全部楼层
here is the result of your code, using "HC164_MOSI_PIN = dat & (1<<i);         //send bits "

void hc164_write2(unsigned char dat) {
        unsigned char i;
       
        for (i=0; i<8; i++) {
                HC164_MOSI_PIN = dat & (1<<i);                                        //send bits
                //HC164_MOSI_PIN = (dat & (1<<i))? 1: 0;
                //HC164_MOSI_PIN = !(!(dat & (1<<i)));                                        //send bits
                HC164_CLK_PIN=1;                                                        //send clock
                HC164_CLK_PIN=0;                                                        //clear clock
        }
}




(原文件名:avr hc164 2.PNG)
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-20 05:01

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表