使用SPI驱动数码管

代码:

7-seg.c

/*
  《AVR专题精选》随书例程
  
  3.通信接口使用技巧

  项目:改进的延时法实现半双工软件串口
  文件:7seg.c
  说明:SPI控制数码管驱动文件
        
  作者:邵子扬
  时间:2012年12月15日

*/

#include <avr/io.h>

extern unsigned char SPI_RW(unsigned char dat);

// LED 数码管数量
#define SEG_CNT   2

// 7 SEG LED, 共阳极字模(共阴极类似)
//
//     0
//    ---
//  5| 6 |1
//    ---
//  4|   |2
//    ---  .7
//     3
//
const unsigned char LEDMASK[] = 
{                        //7654 3210  No
  0xC0,  // 0              1100 0000  0
  0xF9,  // 1              1111 1001  1
  0xA4,  // 2              1001 0100  2
  0xB0,  // 3              1011 0000  3
  0x99,  // 4              1001 1001  4
  0x92,  // 5              1001 0010  5
  0x82,  // 6              1000 0010  6
  0xF8,  // 7              1111 1000  7
  0x80,  // 8              1000 0000  8
  0x90,  // 9              1001 0000  9
  0x88,  // A              1000 1000  10
  0x83,  // b              1000 0011  11
  0xC6,  // C              1100 0110  12
  0xA1,  // d              1010 0001  13
  0x86,  // E              1000 0110  14
  0x8E,  // F              1000 1110  15
  0xC2,  // G              1100 0010  16
  0x89,  // H              1000 1001  17
  0x7F,  // .              0111 1111  18
  0xF1,  // J              1111 0001  19
  0xFF,  // blank          1111 1111  20
  0xC7,  // L              1100 0111  21
  0xBF,  // -              1011 1111  22
  0xF7,  // _              1111 0111  23
  0xA3,  // o              1010 0011  24
  0xA7,  // [              1010 0111  25
  0xE3,  // u              1110 0011  26
  0xB3,  // ]              1011 0011  27
  0xAB,  // n              1010 1011  28
  0xFF,
  0xFF,
  0xFF
};

// 显示驱动文件
void DISP7SEG(unsigned char *ledbuf)
{
  unsigned char i, t;

  // Enable update
  PORTB |= (1 << PB2);

  for(i = 0; i < SEG_CNT; i++)
  {
    t = LEDMASK[ledbuf[i] % 32];
 
    // 缓存最高位控制数据闪烁
    if(ledbuf[i] & 0x80)
      t &= 0x7F;

    SPI_RW(t);
  }

  // Disable update
  PORTB &= ~(1 << PB2);
}

main.c

/*
  《AVR专题精选》随书例程
  
  3.通信接口使用技巧

  项目:SPI驱动数码管
  文件:main.c
  说明:主程序
        
  作者:邵子扬
  时间:2012年12月15日

*/

#include <avr/io.h>

// 系统时钟频率
#define F_CPU  1000000UL

#include <util/delay.h>

#include "macromcu.h"

// 定义SPI端口
#define CS    B, 2
#define SCK   B, 5
#define MOSI  B, 3


/*
  函数说明: SPI初始化
  输入参数:
  mode: b7:      1 slave, 0 master
        b65432:  not use
        b10:     mode  CPOL CPHA
                  3     1    1
                  2     1    0
                  1     0    1
                  0     0    0

  speed: b76543: not use
         b210:   speed   KHz
                   0     500   F/2
                   1     500   F/2
                   2     250   F/4
                   3     125   F/8
                   4     62.5  F/16
                   5     31.25 F/32
                   6     15.63 F/64
                   7     7.81  F/128
                   
*/
void SPI_init(char mode, char speed)
{
  unsigned char bSPR, bSPI2X, bMODE;

  PINDIR(CS,  PIN_OUTPUT);
  PINDIR(SCK, PIN_OUTPUT);
  PINDIR(MOSI,PIN_OUTPUT);

  // SPI mode
  switch(mode%4)
  {
    case 1:// mode 1
      bMODE = (0 << CPOL)|(1 << CPHA);
      break;
    case 2:// mode 2
      bMODE = (1 << CPOL)|(0 << CPHA);
      break;
    case 3:// mode 3
      bMODE = (1 << CPOL)|(1 << CPHA);
      break;
    default:// mode 0
      bMODE = (0 << CPOL)|(0 << CPHA);
      break;
  }

  // Master or Slave
  if((mode & 0x80) == 0)
    bMODE |= (1 << MSTR);

  // SPI speed
  bSPI2X = 0;
  switch(speed)
  {
    case 7:// F/128 = 7.8125K
      bSPR = (1 << SPR1)|(1 << SPR0);
      break;
    case 6:// F/64 = 15.625K
      bSPR = (1 << SPR1)|(0 << SPR0);
      break;
    case 5:// F/32 = 31.25K
      bSPR = (1 << SPR1)|(0 << SPR0);
      bSPI2X = 1;
      break;
    case 4:// F/16 = 62.5K
      bSPR = (0 << SPR1)|(1 << SPR0);
      break;
    case 3:// F/8 = 125K
      bSPR = (0 << SPR1)|(1 << SPR0);
      bSPI2X = 1;
      break;
    case 2:// F/4 = 250K
      bSPR = (0 << SPR1)|(0 << SPR0);
      break;
    default:// F/2 = 500K
      bSPR = (0 << SPR1)|(0 << SPR0);
      bSPI2X = 1;
      break;
  }
  SPCR = (1 << SPE)|bMODE|bSPR;
  SPSR = (bSPI2X << SPI2X);
}

// SPI读写
unsigned char SPI_RW(unsigned char dat)
{
  SPSR &= ~(1 << SPIF);
  SPDR = dat;
  while((SPSR & (1 << SPIF)) == 0);

  return SPDR;
}

// 系统初始化
void init()
{
  SPI_init(0, 0);
}

extern void DISP7SEG(unsigned char *ledbuf);

// LED显示缓存
unsigned char LEDBUF[2];
unsigned char cnt;

int main()
{

  init();  // 初始化

  for(;;)
  {
    _delay_ms(500);  // 延时500ms
    
    cnt++;           // 计数器递增

    LEDBUF[0] = cnt / 16; // 修改缓存内容
    LEDBUF[1] = (cnt % 16)|0x80;

    DISP7SEG(LEDBUF); // 更新显示
  }

  return 0;
}

仿真

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值