代码:
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;
}
仿真