SPI接口实险,动态LED数据管显示实验。
1、程序通过SPI接口输出数据到HC595芯片驱动LED数据管简单显示。
2、动态调度由片内定时器1中断产生,中断周期为5mS。
3、内部1 M晶振,程序采用单任务方式,软件延时。
4、进行此实验请插上JP1的所有8个短路块,JP6(SPI_EN)短路块。
程序采用模块化编程,下面为主函数文件:
#include "iom16v.h"extern unsigned char led_buf[];
extern void Disp_Init(void);
/*延时函数*/void delay_ms(unsigned char i) {
unsigned char a, b;for (a = 1; a < i; a++) {
for (b = 1; b; b++) {
;
}
}
}
void main(void) {
unsigned char i = 0;
DDRA = 0x00;/*方向输入*/PORTA = 0xFF;/*打开上拉*/
DDRB = 0xFF;/*方向输出*/
PORTB = 0xF0;/*电平设置*/
DDRC = 0x00;
PORTC = 0xFF;
DDRD = 0x00;
PORTD = 0xFF;
delay_ms(200);Disp_Init();
while (1) {
i ++;
delay_ms(100);
led_buf[3] = 0;
led_buf[2] = i / 100;
led_buf[1] = (i % 100) / 10;
led_buf[0] = (i % 10);
}
}
数码管显示函数文件
#include "iom16v.h"
#include <macros.h>
unsigned char disp[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0};
unsigned char led_buf[] = {1, 2, 3, 4, 0};/*显示信息*/
/*------------------------------------------------------------------*-
Disp_Init()显示初始化
-*------------------------------------------------------------------*/void Disp_Init(void) {
/*初始化定时器*/OCR1A = 625;/*计数周期为5mS,F=1M*/
TIMSK |= (1 << OCIE1A);/*比较中断A允许*/
SREG = 0x80;
TCCR1A = 0x00;
TCCR1B = 0x08;/*定时器工作在CTC计数器模式*/
TCCR1B |= 0x02;/*设置定时器的分频值为8分频*/
/*SPI接口初始化*/
DDRB |= (1<<PB5) | (1<<PB7);/* 设置MOSI 和SCK 为输出,其他为输入 */
SPCR = (1<<SPE) | (1<<MSTR)
| (1<<SPR1) | (1<<SPR0);/* 使能SPI 主机模式,时钟为fck/128 */
/*中断使能*/
SEI();
}
/*------------------------------------------------------------------*-Int_TCCR1A()
LED数码管动态显示函数
定时器'T1',A组比较中断产生5mS周期性中断在中断里刷新显示
-*------------------------------------------------------------------*/
#pragma interrupt_handler Int_TCCR1A: 7
void Int_TCCR1A(void) {
unsigned char temp;static unsigned char i;
PORTB &= ~(1 << 4);/*准备锁存*/PORTB |= 0x0F;
PORTB |= (1 << 4);/*锁存数据*/
if (i == 3) {
PORTB &= ~(1 << 2);
}
if (i == 2) {
PORTB &= ~(1 << 1);
}
if (i == 1) {
PORTB &= ~(1 << 0);
}
if (i == 0) {
PORTB &= ~(1 << 3);
}
temp = led_buf[i] % 16;/**/
temp = disp[temp];/**/
SPDR = temp;
if (i > 3) {i = 0;
}
else {
i ++;
}
}