|
发表于 2011-7-10 21:15:06
|
显示全部楼层
here is a slightly more structured way to approaching your code.
it basically replicated your code, giving it more structure, and adds some features / flexibility:
1) it has a blinking half second indicator;
2) it accomodates either common cathode or common anode displays;
3) it runs on pretty much any frequencies - you just need to redefine F_CPU;
4) most importantly, its timing error is only dependent on the crystal used, and it provides a way for you to correct your timing error.
hope it helps.- //time keeping on 8051
- //tmr0 runs as a 16-bit rtc (black roman approach)
- //tmr1 controls the 7-segment display
- #include<regx51.h> //we use keil c51
- #include "gpio.h"
- #include <intrins.h>
- //hardware configuration
- #define _7SEG_PORT P2 //7seg connection, active low
- #define _7SEG_DDR P2
- #define _7SEGs 0xff
- #define _7SEG_OFF(segs) {_7SEG_PORT= (segs);} //turn on segments, active low
- #define _7SEG_ON(segs) {_7SEG_PORT=~(segs);} //turn off segments
- #define DIG_PORT P3 //digits connection, active high
- #define DIG_DDR P3
- #define DIGs 0xff
- #define DIG_ON(digs) {DIG_PORT= (digs);} //turn on digs, active high
- #define DIG_OFF(digs) {DIG_PORT=~(digs);} //turn off digs
- #define HALF_SEC (500000ul) //half a second, in us
- #define FULL_SEC (2*HALF_SEC) //a full second, in us
- #define TMR0_PERIOD HALF_SEC //tmr0's period
- #define TMR1_PERIOD 1000ul //tmr1's period
- #define TMR0_ERROR 0 //tmr0 error term
- //end hardware configuration
- #define F_CPU 2000000ul //cpu frequency, in hz
- #define DLY_MS 100 //delay cycles to achieve 1ms at 1MIPS
- #define MSB(word_t) ((word_t) >> 8) //word_t's most significant byte
- #define LSB(word_t) ((word_t) & 0x00ff) //word_t's least significant byte
- typedef struct {
- unsigned char half_sec; //half second
- unsigned char sec; //second
- unsigned char fen; //minute
- unsigned char shi; //hour
- } _time_type;
- //global variables
- unsigned long _time_counter=0; //time counter, in timer ticks
- unsigned short _tmr1_period; //tmr1 period
- _time_type _time={ //time for time keeping
- 0, 59, 59, 23}; //23:59:59:0
- unsigned char vRAM[8]; //display buffer
- unsigned char disp_on_off,disp,i,sec1,sec,fen,shi;
- //sbit =P2;
- //unsigned int count;
- sbit k1=P1^0; //??,???? ???????
- void delay(unsigned char dly) {
- while (dly--) continue;
- }
- void delay_ms(unsigned char ms) //????
- {
- //unsigned char i,k;
- while (ms--)
- delay(DLY_MS * (F_CPU / 1000000ul));
- }
- /****************??0??***************/
- void tmr0_init(void)
- {
- TR0=0; //stop tmr0
- TMOD= (TMOD & 0xf0) | //reset tmod's lower 4 bits
- 0x01; //tmr0 running in mode 1 (16-bit timer), not gated
- TH0=0; //reset tmr0
- TL0=0;
- ET0=1; //enable tmr0 interrupt
- // EA=1;
- TR0=1;
- }
- //update time
- void update_time(_time_type * time) {
- _time_counter+=0x10000ul+TMR0_ERROR; //increment time_counter;
- if (_time_counter >= (TMR0_PERIOD * (F_CPU / 1000000ul))) { //need to make sure that it doesn't overflow at high f_cpu
- //IO_FLP(P1, 1<<1); //for testing only
- _time_counter -= (TMR0_PERIOD * (F_CPU / 1000000ul)); //reset _time_counter
- time->half_sec+=1; //increment half second
- if(time->half_sec==2) //full second reached?
- {
- time->half_sec=0; //reset half second indicator
- time->sec+=1; //increment the second
- if(time->sec==60) //full 60 seconds passed?
- {
- time->sec=0; //reset the second
- time->fen+=1; //increment the minute
- if(time->fen==60) //full 60 minutes passed?
- {
- time->fen=0; //reset the minute
- time->shi+=1; //increment the hour
- if(time->shi==24) //full 24 hour passed?
- {
- time->shi=0; //reset the hour
- }
- vRAM[5]=0x10; //update hour display
- vRAM[6]=time->shi%10;
- vRAM[7]=time->shi/10;
- }
- vRAM[3]=time->fen%10; //update minute display
- vRAM[4]=time->fen/10;
- }
- vRAM[0]=time->sec%10; //??????? //update second display
- vRAM[1]=time->sec/10;
- }
- vRAM[2]=(time->half_sec)?0x10:0x7f; //???? - blinking
- }
- }
- /****************??0??*************/
- void tmr0_isr(void) interrupt TF0_VECTOR
- {
- update_time(&_time); //update time keeping
- }
- //initialize the display
- void _7seg_init(void) {
- _7SEG_OFF(_7SEGs); //clear leds - turn off all segments
- IO_OUT(_7SEG_DDR, _7SEGs); //leds as output
- DIG_OFF(DIGs); //all display off
- IO_OUT(DIG_DDR, DIGs); //all digit pins as output
- //initialize vRAM
- vRAM[5]=0x10; //update hour display
- vRAM[6]=_time.shi%10;
- vRAM[7]=_time.shi/10;
- vRAM[3]=_time.fen%10; //update minute display
- vRAM[4]=_time.fen/10;
- vRAM[0]=_time.sec%10; //??????? //update second display
- vRAM[1]=_time.sec/10;
- vRAM[2]=(_time.half_sec)?0x10:0x7f; //???? - blinking the half second indicator
- }
- //display the content of vRAM[8]
- void _7seg_display(void) {
- unsigned char code _7seg_font[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40};//???????
- //unsigned char _7seg_font[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; //???????????
- static unsigned char digit=0; //digit to be displayed
- DIG_OFF(DIGs); //turn all digits off
- _7SEG_ON(_7seg_font[vRAM[digit]]); //display the digit
- DIG_ON(1<<digit); //turn on the digit
- digit+=1; //increment the digit
- if (digit==8) digit=0; //reset the digit
- }
- /****************??1??***************/
- void tmr1_init(unsigned short period)
- {
- _tmr1_period=period; //save tmr1_period
- TR1=0; //stop tmr1
- TMOD= (TMOD & 0x0f) | //reset tmod's higher 4 bits
- 0x10; //tmr1 running in mode 1 (16-bit timer), not gated
- TH1=MSB(-_tmr1_period); //load up the offset
- TL1=LSB(-_tmr1_period);
- ET1=1;
- //EA=1;
- TR1=1;
- }
- /***************??1????***********/
- void tmr1_isr(void) interrupt TF1_VECTOR
- {
- //IO_FLP(P1, 1<<2); //for testing only
- TH1+=MSB(-_tmr1_period); //load up the offset
- TL1+=LSB(-_tmr1_period); //load up the offset
- _7seg_display(); //display
- }
- void mcu_init(void) {
- }
- void main(void) //???
- {
- //shi=12;
- //fen=12;
- //P0=0xff;
- //disp_on_off=0xfe; //?????
- //disp=0;
- mcu_init(); //reset the mcu
- _7seg_init(); //reset the 7seg display
- tmr0_init(); //reset tmr0 - period set by TMR0_PERIOD
- tmr1_init(TMR1_PERIOD * (F_CPU / 1000000ul)); //reset tmr1
- EA=1; //enable global interrupt
- while(1)
- {
- //delay();
-
- }
- }
复制代码 |
|