搜索
bottom↓
回复: 14

模拟SPI,74HC595驱动数码管(GCC和IAR)

[复制链接]

出0入0汤圆

发表于 2010-10-4 22:31:38 | 显示全部楼层 |阅读模式
模拟SPI,74HC595驱动数码管,用了GCC和IAR,IAR的位操作确实很方便,调试程序方便。此为模拟SPI。

以下为源程序:

(1)GCC:

//名称:模拟SPI,74HC595驱动数码管
//功能:74HC595驱动数码管
//机型:ATmega16    使用晶振7.3728M
//作者:RM QQ:731424304 百度空间:http://hi.baidu.com/change_ghost/home
//程序版本:V1.0
//维护记录:2010.10.4
//欢迎大家和我一起交流学习,转载请保持源文件的完整性。
//任何单位和个人不经本人允许不得用于商业用途
//硬件接线:见电路图,程序用于ATmega16_Basic_V1.2开发板,具体接线请参考其电路图,网上可搜到
//595接线:
//PB4----------RCK
//PB5----------Ds
//PB6----------CLR
//PB7----------SCK

#include<avr/io.h>
#include<avr/delay.h>
#define uchar unsigned char
#define uint unsigned int
//////////////////////////////////////////////////////////////////////
unsigned char gyadx[24]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,
                         0X82,0XF8,0X80,0X90,0X88,0X83,
          0XC6,0XA1,0X86,0X8E,0X89,0X8C,
          0XC7,0XA7,0X84,0X8B,0XAB,0x98};
//0~9,A~F;大写H,P,大写L,小写c,小写e,小写h,小写n,小写q,共阳码
unsigned char gyidx[24]={0X3F,0X06,0X5B,0X4F,0X66,0X6D,
                         0X7D,0X07,0X7F,0X6F,0X77,0X7C,
          0X39,0X5E,0X79,0X71,0X76,0X73,
          0X38,0X58,0X7B,0X74,0X54,0x67};
//0~9,A~F;大写H,P,大写L,小写c,小写e,小写h,小写n,小写q//共阴码

void delay_ms(uint ms)
{
while(--ms)
{ _delay_ms(1); }
}

////////////////////////////////////////////////////////////
int dadiplay(uint data)//要传输的数据
{   
PORTB=0XFF;
    DDRB=0XFF;                  //低四位上拉
uchar i;

    for(i=0;i<8;i++)
     {   
      if( (data&0X80) ==0X80 )//数据第八位为1为真,获取最高位数据
         PORTB|=0X20;//数据输入脚PB5=1
      else
   // PORTB&=~0X20;//数据输入脚PB5=0,这一句也可以
        PORTB&=0XDF;//数据输入脚PB5=0
   PORTB&=0X7F;//PB7 sck=0
        PORTB|=0X80;//PB7 sck=1上升沿
      data<<=1;
      }
   PORTB&=0XEF;
    PORTB|=0X10;              //595移位寄存器的数据进入数据存储寄存器,并在数码管上显示


}


////////////////////////////////////////////////////////////
int main()
{
   PORTD=0X00;
   DDRD=0XFF;
   uchar i;
   while(1)
   {
   for(i=0;i<24;i++)
      {
       dadiplay(gyadx);
    delay_ms(5000);
      }
   }

}


(2)IAR:

//名称:模拟SPI,74HC595驱动数码管
//功能:74HC595驱动数码管
//机型:ATmega16    使用晶振7.3728M
//作者:RM QQ:731424304 百度空间:http://hi.baidu.com/change_ghost/home
//程序版本:V1.0
//维护记录:2010.10.4
//欢迎大家和我一起交流学习,转载请保持源文件的完整性。
//任何单位和个人不经本人允许不得用于商业用途
//硬件接线:见电路图,程序用于ATmega16_Basic_V1.2开发板,具体接线请参考其电路图,网上可搜到
//595接线:
//PB4----------RCK
//PB5----------Ds
//PB6----------CLR
//PB7----------SCK

#include<iom16.h>
#define uchar unsigned char
#define uint unsigned int
#define DAT PORTB_Bit5
#define SCK PORTB_Bit7
#define RCK PORTB_Bit4

//////////////////////////////////////////////////////////////////////
unsigned char gyadx[24]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,
                         0X82,0XF8,0X80,0X90,0X88,0X83,
          0XC6,0XA1,0X86,0X8E,0X89,0X8C,
          0XC7,0XA7,0X84,0X8B,0XAB,0x98};
//0~9,A~F;大写H,P,大写L,小写c,小写e,小写h,小写n,小写q
unsigned char gyidx[24]={0X3F,0X06,0X5B,0X4F,0X66,0X6D,
                         0X7D,0X07,0X7F,0X6F,0X77,0X7C,
          0X39,0X5E,0X79,0X71,0X76,0X73,
          0X38,0X58,0X7B,0X74,0X54,0x67};
//0~9,A~F;大写H,P,大写L,小写c,小写e,小写h,小写n,小写q


void port_init(void)
{
    DDRA = 0XFF;
    PORTA = 0X00;
    DDRB = 0XFF;
    PORTB = 0XFF;
    DDRC = 0XFF;
    PORTC = 0XFF;
    PORTD=0X7F;
    DDRD=0XFF;
}

void devices_init(void)
{
    port_init();
}

/************************** 数码管驱动程序 ***********************/
int dadiplay(uint data)//要传输的数据
{
#define DAT PORTB_Bit5
#define SCK PORTB_Bit7
#define RCK PORTB_Bit4

      uchar j;
      for (j=0;j<8;j++)
     {
    // DAT = data & (0x80>>j);        //只可以这样送数据
             if( (data&0x80) ==0x80)//数据第八位为1为真,获取最高位数据
         DAT=1;//miso=1 数据输入脚PB5
           else
   DAT=0;//miso=0   1101 1111                 
             SCK = 0;                     //上升沿发生移位
             SCK = 1;
            data=data <<1;   
}
       RCK = 0;
       RCK = 1; //上升沿将数据送到输出锁存器
            
}

void delay_ms(uint t)
{
    uint i,j;
    for(i=0;i<t;i++)
      for(j=0;j<1140;j++);
}

void main(void)
{
   devices_init();
   uchar i;
   while(1)
   {
   for(i=0;i<24;i++)
      {
       dadiplay(gyadx);
    delay_ms(1000);
      }
   }
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

 楼主| 发表于 2010-10-5 19:38:38 | 显示全部楼层
回复【楼主位】change1
-----------------------------------------------------------------------

SPI,74HC595驱动数码管(GCC和IAR)

//名称:SPI,74HC595驱动数码管
//功能:74HC595驱动数码管
//机型:ATmega16    使用晶振7.3728M
//作者:RM  QQ:731424304  百度空间:http://hi.baidu.com/change_ghost/home
//程序版本:V1.0
//维护记录:2010.10.5
//编译器:GCC for AVR
//欢迎大家和我一起交流学习,转载请保持源文件的完整性。
//任何单位和个人不经本人允许不得用于商业用途
//硬件接线:见电路图,程序用于ATmega16_Basic_V1.2开发板,具体接线请参考其电路图,网上可搜到
//595接线:
//PB4----------RCK
//PB5----------Ds
//PB6----------CLR
//PB7----------SCK
#include<avr/io.h>
#include<avr/delay.h>
/***************************************************************************************/
#define BIT(x)        (1<<(x))
#define NOP()        asm("nop")
#define WDR()         asm("wdr")
#define uchar        unsigned char
#define uint        unsigned int
#define ulong   unsigned long
#define schar    signed   char
#define sint    signed   int
#define slong   signed   long
/***************************************************************************************/
void port_init(void)
{
        PORTA = 0x00;
        DDRA  = 0xFF;
        PORTB = 0x00;
        DDRB  = 0xFF;
        PORTC = 0x00;
        DDRC  = 0xFF;
        PORTD = 0x00;
        DDRD  = 0xFF;
}
void init_devices(void)
{
  port_init();
}
/***************************************************************************************/
uchar gyadx[25]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,
                         0X82,0XF8,0X80,0X90,0X88,0X83,
                         0XC6,0XA1,0X86,0X8E,0X89,0X8C,
                         0XC7,0XA7,0X84,0X8B,0XAB,0X98,0XC1};
//0~9,A~F;大写H,P,大写L,小写c,小写e,小写h,小写n,小写q,大写U     //共阳码
uchar gyidx[25]={0X3F,0X06,0X5B,0X4F,0X66,0X6D,
                         0X7D,0X07,0X7F,0X6F,0X77,0X7C,
                         0X39,0X5E,0X79,0X71,0X76,0X73,
                         0X38,0X58,0X7B,0X74,0X54,0x67,0X3E};
//0~9,A~F;大写H,P,大写L,小写c,小写e,小写h,小写n,小写q,大写U    //共阴码

/***************************************************************************************/
void SPImasterInit(void)     //SPI初始化
{
  DDRB|=(1<<7)|(1<<5);       //设置SCK,MOSI为输出,其他为输入
  SPCR=(1<<6)|(1<<4)|(1<<1)|(1<<0);//使能SPI,主模式,Fck/128
}  
/***************************************************************************************
函数名称: void SPIMasterTransmit(uchar TranData)
函数功能: SPI数据传输
参    数:
返 回 值: 无
****************************************************************************************/
void SPIMasterTransmit(unsigned char TranData)   
{
  SPDR=TranData;                       //数据放入SPI寄存器中
  while(!(SPSR&(1<<7)));               //等待数据传输完毕
}

/***************************************************************************************
函数名称: void display(uchar i)
函数功能: 74HC595数据输出显示
参    数:
返 回 值: 无
***************************************************************************************/
int display(unsigned char i)
{
   PORTB&=~(1<<4);             //等待数据传输,595存储寄存器数据不变
   SPIMasterTransmit(i);       //传输数据
   PORTB|=(1<<4);              //595移位寄存器的数据进入数据存储寄存器,并在数码管上显示
}
/***************************************************************************************/
//延时函数
int delay_ms(uint ms) //毫秒级
{
        while(--ms)
        {         _delay_ms(1);        }
}


int delay_us(uint us) //微妙级
{
        while(--us)
        {         _delay_us(1);        }
}
/***************************************************************************************/
//主函数
int main()
{  
    init_devices();
    SPImasterInit();
    uchar i;
    PORTD=0X00;
    DDRD=0XFF;
    while(1)
    {
      for(i=0;i<25;i++)  
      {
          display(gyadx);
          delay_ms(500);
      }
    }
}





//名称:SPI,74HC595驱动数码管
//功能:74HC595驱动数码管
//机型:ATmega16    使用晶振7.3728M
//作者:RM  QQ:731424304  百度空间:http://hi.baidu.com/change_ghost/home
//程序版本:V1.0
//维护记录:2010.10.5
//编译器:IAR for AVR5.30
//欢迎大家和我一起交流学习,转载请保持源文件的完整性。
//任何单位和个人不经本人允许不得用于商业用途
//硬件接线:见电路图,程序用于ATmega16_Basic_V1.2开发板,具体接线请参考其电路图,网上可搜到
//595接线:
//PB4----------RCK
//PB5----------Ds
//PB6----------CLR
//PB7----------SCK
#include<iom16.h>
//端口定义
#define DATA PORTB_Bit5
#define SCK  PORTB_Bit7
#define RCK  PORTB_Bit4
#define CLR  PORTB_Bit6
////////////////////////////////////////////////////////////////////
#define BIT(x)        (1<<(x))
#define NOP()        asm("nop")
#define WDR()         asm("wdr")
#define uchar        unsigned char
#define uint        unsigned int
#define ulong   unsigned long
#define schar    signed   char
#define sint    signed   int
#define slong   signed   long
////////////////////////////////////////////////////////////////////
void port_init(void)
{
        PORTA = 0x00;
        DDRA  = 0xFF;
        PORTB = 0x00;
        DDRB  = 0xFF;
        PORTC = 0x00;
        DDRC  = 0xFF;
        PORTD = 0x00;
        DDRD  = 0xFF;
}
void init_devices(void)
{
  port_init();
}
////////////////////////////////////////////////////////////////////
uchar gyadx[25]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,
                         0X82,0XF8,0X80,0X90,0X88,0X83,
                         0XC6,0XA1,0X86,0X8E,0X89,0X8C,
                         0XC7,0XA7,0X84,0X8B,0XAB,0X98,0XC1};
//0~9,A~F;大写H,P,大写L,小写c,小写e,小写h,小写n,小写q,大写U共阳码
uchar gyidx[25]={0X3F,0X06,0X5B,0X4F,0X66,0X6D,
                         0X7D,0X07,0X7F,0X6F,0X77,0X7C,
                         0X39,0X5E,0X79,0X71,0X76,0X73,
                         0X38,0X58,0X7B,0X74,0X54,0x67,0X3E};
//0~9,A~F;大写H,P,大写L,小写c,小写e,小写h,小写n,小写q,大写U//共阴码

/*-----------------------------------------------------------------*/
void SPImasterInit(void)     //SPI初始化
{
  DDRB|=(1<<7)|(1<<5);       //设置SCK,MOSI为输出,其他为输入
  SPCR=(1<<6)|(1<<4)|(1<<1)|(1<<0);//使能SPI,主模式,Fck/128
}  
/*-----------------------------------------------------------------
函数名称: void SPIMasterTransmit(uchar TranData)
函数功能: SPI数据传输
参    数:
返 回 值: 无
-----------------------------------------------------------------*/
void SPIMasterTransmit(unsigned char TranData)   
{
  SPDR=TranData;                       //数据放入SPI寄存器中
  while(!(SPSR&(1<<7)));               //等待数据传输完毕
}

/*-----------------------------------------------------------------
函数名称: void display(uchar i)
函数功能: 74HC595数据输出显示
参    数:
返 回 值: 无
-----------------------------------------------------------------*/
void display(unsigned char i)
{
   PORTB&=~(1<<4);             //等待数据传输,595存储寄存器数据不变
   SPIMasterTransmit(i);       //传输数据
   PORTB|=(1<<4);              //595移位寄存器的数据进入数据存储寄存器,并在数码管上显示
}
////////////////////////////////////////////////////////////////////
//非精确定时
int delay_ms(uint t)
{
    uint i,j;
    for(i=0;i<t;i++)
      for(j=0;j<1140;j++);
}
int main()
{  
    init_devices();
    SPImasterInit();
    uchar i;
    PORTD=0X00;
    DDRD=0XFF;
    while(1)
    {
      for(i=0;i<25;i++)  
      {
          display(gyadx);
          delay_ms(500);
      }
    }
}

出0入0汤圆

发表于 2011-1-11 20:50:27 | 显示全部楼层
谢谢楼主分享

出0入0汤圆

发表于 2011-6-30 01:07:47 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-7-20 23:31:43 | 显示全部楼层
回复【4楼】wuxin999
-----------------------------------------------------------------------

有个疑问,1楼的第一个用SPI实现的程序,烧到开发板上8个数码管全都只显示8,只有当我把void port_init(void) 端口初始化中的B口改成PORTB=0xff后,才正常依次显示,个人感觉后面对PORTB重新赋的值才是真正有显示功能的,而这种初始化没多大实际用处,但这里为什么就这么关键呢?
求大侠们指点小弟O(∩_∩)O~

出0入0汤圆

发表于 2011-8-21 14:17:37 | 显示全部楼层
谢谢分享!

出0入0汤圆

发表于 2011-10-2 03:37:38 | 显示全部楼层
Mark

出0入0汤圆

发表于 2011-10-19 10:56:37 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-10-19 18:53:46 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-9-24 15:41:43 | 显示全部楼层
学习下

出0入0汤圆

发表于 2012-9-25 04:20:42 | 显示全部楼层
有个疑问


because the posted code is 1) essentially wrong; and 2) not portable.

出0入0汤圆

发表于 2012-9-25 07:59:33 | 显示全部楼层
here is something that you can use on multiple mcus / compilers, with minimal changes - mostly device-specific header files.

hc595.h


  1. #ifndef __HC595_H
  2. #define __HC595_H

  3. //hardware configuration
  4. #define HC595_PORT                PORTB                //hc595's port
  5. #define HC595_DDR                DDRB                //hc595's ddr
  6. #define HC595_SCK                (1<<1)                //serial clock
  7. #define HC595_MOSI                (1<<2)                //master out, slave in
  8. #define HC595_RCK                (1<<7)                //rck to transfer data to output registers
  9. //end hardware configuration

  10. void hc595_init(void);

  11. unsigned char hc595_write(unsigned char data_byte);

  12. #endif //hc595_h
复制代码
hc595.c


  1. //#include <regx51.h>                                        //we use c51
  2. #include <avr/io.h>                                                //we use avr
  3. #include "gpio.h"
  4. #include "hc595.h"

  5. void hc595_init(void) {
  6.         IO_CLR(HC595_PORT, HC595_SCK | HC595_MOSI | HC595_RCK);                //clear hc595 pins
  7.         IO_OUT(HC595_DDR, HC595_SCK | HC595_MOSI | HC595_RCK);                //hc595 pins as output
  8. }

  9. unsigned char hc595_write(unsigned char data_byte) {
  10.         unsigned char mask = 0x80;                        //send highest bit first

  11.         //IO_SET(HC595_PORT, HC595_RCK);                //force a high->low transition on the latch
  12.         IO_CLR(HC595_PORT, HC595_RCK);                //clear rck / sck
  13.         do {
  14.                 IO_CLR(HC595_PORT, HC595_SCK);        //clear the clock
  15.                 if (mask & data_byte) IO_SET(HC595_PORT, HC595_MOSI);
  16.                 else IO_CLR(HC595_PORT, HC595_MOSI);
  17.                 IO_SET(HC595_PORT, HC595_SCK);        //strobe out the data
  18.                 mask = mask >> 1;                                //shift to the next bit
  19.         } while (mask);
  20.         IO_CLR(HC595_PORT, HC595_SCK);                //sck cleared
  21.         IO_SET(HC595_PORT, HC595_RCK);                //stroke out data

  22.         return 0;
  23. }
复制代码
application code / example:
  1. /*
  2. */

  3. #include <avr/io.h>                                                        //we use gcc-avr
  4. #include "gpio.h"
  5. #include "hc595.h"                                                        //we use hc595

  6. //hardware configuration
  7. //end hardware configuration

  8. void mcu_init(void) {                                                //reset the mcu
  9. }

  10. int main(void) {
  11.         unsigned char i=1;                                                //tmp variable

  12.         mcu_init();                                                                //reset the mcu
  13.         hc595_init();                                                        //reset hc595

  14.         while(1) {
  15.                 hc595_write(i++);                                        //send i
  16.         }

  17.         return 0;
  18. }
复制代码
so all you need to do in your code is to include "hc595.h", and "hc595.c" and then you can call hc595_write() to send data.

出0入0汤圆

发表于 2012-9-25 08:00:27 | 显示全部楼层
as presented, the code can initialize and write data to 1 hc595.

you can easily modify the code so you can hang multiple hc595s off the same bus and write to multiple of them.

出0入0汤圆

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

本版积分规则

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

GMT+8, 2024-7-23 22:18

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

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