|
发表于 2011-1-19 04:49:13
|
显示全部楼层
"这2点是更高层次的要求了。"
putting a routine inside of an isr is just fundamentally flaw.
your code has the right structure - updating the display through a display buffer but you made it unnecessarily complicated.
here is mine - originally written for 8051. It uses an overflow timer so to maintain portability (to other mcus).
the rows are driven via a hc164, making the design idea to be expanded to drive a message board, by chaining hc164 (or a hc595).
============code==========
//#include <regx51.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include "gpio.h"
//#include "delay.h"
//hardware configuration
#define COL_PORT PORTA //columns are driven by P2
#define COL_DDR DDRA
#define COL_PINs 0xff //all pins on p2
#define COL_DLY 1000 //delay cycles for each col
#define HC164_PORT PORTB
#define HC164_DDR DDRB
#define HC164_CLK (1<<1) //hc164 clock
#define HC164_SDA (1<<2) //hc164 data out
#define HC164_CLR(pin) IO_CLR(HC164_PORT, pin) //clear a hc164 pin
#define HC164_SET(pin) IO_SET(HC164_PORT, pin) //set a hc164pin
//hardware configuration
//strobe pins on rising edge
#define HC164_STROBE(pins) {IO_CLR(HC164_PORT, pins); IO_SET(HC164_PORT, pins);}
//tmr1 offset
unsigned short _tmr1_ticks=0x0000; //display interval for each column
#define MSB(word_t) ((word_t) >> 8) //most significant byte
#define LSB(word_t) ((word_t) & 0x00ff) //least significant byte
//driving mechanism: col low, + hc164 high to turn on a dot on the matrix (common cathode)
const unsigned char font_8x8[3][8] = { //asci font
{0x1f, 0x28, 0x48, 0x88, 0x48, 0x28, 0x1f, 0x00}, //'A'
{0xff, 0x91, 0x91, 0x91, 0x91, 0xaa, 0x44, 0x00}, //'B'
{0x7e, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x00} //'C'
};
unsigned char disp_buffer[8] = { //each column is a byte. 0=right most col
//0x1f, 0x28, 0x48, 0x88, 0x48, 0x28, 0x1f, 0x00
//0xff, 0x91, 0x91, 0x91, 0x91, 0xaa, 0x44, 0x00
0x7e, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x00
//0xff, 0xf0, 0xf0, 0x0f, 0xff, 0xff, 0x55, 0x22
}; //start with a blank space
//unsigned char disp_str[]="ABCBABBAC"; //ascii string to be displayed
//unsigned char *disp_str_ptr=disp_str; //display col index
void _8x8_init(void) {
IO_CLR(COL_PORT, COL_PINs); //all col low
IO_OUT(COL_DDR, COL_PINs); //all col as output
IO_CLR(HC164_PORT, HC164_CLK | HC164_SDA); //_clk / _sda low
IO_OUT(HC164_DDR, HC164_CLK | HC164_SDA); //_clk / _sda as output
}
void tmr1_init(unsigned short ticks) { //set tmr1 to trip once every ticks
_tmr1_ticks = -ticks;
//EA = 0; //disable interrupt
cli();
//TR0=0; //turn off tmr0
TCCR1B = 0x00; //stop the timer
//TMOD = (TMOD & 0xf0) | 0x01; //tmr0: not gated, timer, mode 1 (16 bit tmr)
TCCR1A = (0 << COM1A1) | (0 << COM1A0) | //com0a1..0 = 0b00
(0 << COM1B1) | (0 << COM1B0) | //com0b1..0 = 0b00
(0 << WGM11) | (0 << WGM10) //wgm2..0 = 0b000 -> normal operation
;
TCCR1B = (0 << FOC1A) | //force output channe a disabled
(0 << FOC1B) | //force output channel b disabled
(0 << WGM12) | //wgm12..0 = 0b000 -> normal operation
(0 << CS12) | (0 << CS11) | (1 << CS10) //cs12..0 = 0b001 -> 1:1 prescaler
;
//TH0 = MSB(_tmr0_ticks); //load up the offset
//TL0 = LSB(_tmr0_ticks);
TCNT1 = _tmr1_ticks; //8-bit timer/counter
//TR0 = 1; //turn on tmr0
//ET0 = 1; //turn on tmr0 interrupt
TIMSK1 = (0 << OCIE1B) | //output compare match interrupt on B disabled
(0 << OCIE1A) | //output compare match interrupt on a disabled
(1 << TOIE1) //tmr0 interrupt enabled
;
//EA = 1; //turn on global interrupt
}
//void tmr0_isr(void) interrupt TF0_VECTOR {
ISR(TIMER1_OVF_vect) {
static unsigned current_col=0; //current display
//TH0 += MSB(_tmr0_ticks); //update the offset
//TL0 += LSB(_tmr0_ticks);
TCNT1 += _tmr1_ticks; //advance tmr1 counter
//send 0 on current_col = 0; 1 otherwise
if (current_col) IO_CLR(HC164_PORT, HC164_SDA);
else IO_SET(HC164_PORT, HC164_SDA);
HC164_STROBE(HC164_CLK); //strobe out the data on sda
//COL_PORT = 0x00; //turn off all columns
COL_PORT = disp_buffer[current_col]; //display current buffer
current_col = (current_col + 1) % 8; //update current_col;
}
void mcu_init(void) {
}
int main(void) {
//unsigned char i=0,j=0;
mcu_init(); //reset the mcu
_8x8_init(); //initialize the matrix
tmr1_init(COL_DLY); //set tmr0 to trip every 1000 ticks (=1ms) = 1ms per column
sei(); //turn on global interrupt
while (1) {
//i++;
//_8x8_disp(); //display the current buffer on the leds
}
} |
|