很久以前曾購買"時鐘4位led",找東西時不小心浮上桌面,隨手銲一片洞洞板,線路如上圖,然後分別在89E58,Atmega16,Nuc100執行一樣功能的程序
笙泉89E58
atmel的Atmega16
新唐NUC100
由下面3支程序可看出,C 在跨平台上,真的很方便 主程式並沒有做甚麼改變,不同處只有各自的TIMER設定,GPIO設定及位(BIT)操作,我一直以來都是用8X51組合語言在寫程序,偶而用PIC16F5X組合語言,自從接觸到 LPC2103(ARM7)後,強烈感覺用C真的比組合語言輕鬆很多,深刻感覺大勢所趨 呵呵 ,另外 一個趨勢"ARDUINO"這個板子,對初學者應該很便利,個人感到快被"ARDUINO"淹沒, Atmel Atmega系列因"ARDUINO"而得以熱銷,對Atmel 是件好事, 但感覺好像有點怪怪的,你有感覺到嗎?
//89e58程序 IDE KEIL C
// Function:時鐘計時
// 基板:
#include "REG_MPC89L51-515.H"
#include "INTRINS.H"
// io port Description
#define _ONE P10 //個
#define _TWO P11 //拾
#define _THREE P12 //百
#define _FOUR P13 //千
#define KEY P42
const _7_seg[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xd8,0x80,0x90,0xff };
unsigned char time_cnt,min_cnt=43,hour_cnt=12,show_time=0;
unsigned char _1_sec_cnt=0x28 ; //一秒 計時
unsigned char scan_cnt=0X00; //顯示掃瞄的位數指標
unsigned char disp_0,disp_1,disp_2,disp_3;
bit _05sec,hour_sw=0;
//-------------------------------------------------
void Init_IRQ()
{
ET1 = 0x01; //Enable Timer Interrupt 1
TMOD = 0X10 ;
TH1 = 0X3C ;
TL1 = 0XB0 ;
EA = 0x01 ; //Enable All Interrupt
TR1 = 0X01 ; //START TIMER1
}
void Timer_Interrupt_1() interrupt 3
{
_1_sec_cnt -- ;
if (_1_sec_cnt==0) // 計算 1秒
{ time_cnt ++ ;
_1_sec_cnt=0x28 ;
}
if(_1_sec_cnt>=0x14) // 產生0.5 Sec
{_05sec=1;}
else {_05sec=0;}
if (time_cnt>=60) //每60秒進一
{ min_cnt+=1;
time_cnt=0;
}
if (min_cnt>=60) //每60分進一
{ hour_cnt+=1;
min_cnt=0;
}
TH1 = 0X3C ;
TL1 = 0XB0 ;
}
main()
{
Init_IRQ();
//-----------------------------------------------
while (1)
{
if (scan_cnt>3) scan_cnt=0x00;
switch(scan_cnt)
{case 0:
P2=0XFF;
_ONE=0x00;
_TWO=0x01;
_THREE=0X01;
_FOUR=0X01;
if (05sec==1) {P2= _7_seg[disp_0]&0x7f;}else {P2= _7_seg[disp_0]|0x80;}
// P2= _7_seg[disp_0] ;
scan_cnt ++ ;
break;
case 1:
P2=0XFF;
_ONE=0x01;
_TWO=0x00;
_THREE=0X01;
_FOUR=0X01;
if (05sec==1) {P2= _7_seg[disp_1]&0x7f;}else {P2= _7_seg[disp_1]|0x80;}
// P2= _7_seg[disp_1] ;
scan_cnt ++ ;
break;
case 2:
P2=0XFF;
_ONE=0x01;
_TWO=0x01;
_THREE=0X00;
_FOUR=0X01;
P2= _7_seg[disp_2] ;
scan_cnt ++ ;
break;
case 3:
P2=0XFF;
_ONE=0x01;
_TWO=0x01;
_THREE=0X01;
_FOUR=0X00;
P2= _7_seg[disp_3] ;
scan_cnt ++ ;
break;
}
disp_0 = time_cnt % 10 ;
disp_1 = (time_cnt/10)%10 ;
disp_2= (min_cnt%10);
disp_3 = (min_cnt/10)%10 ;
}
}
//----------------------------------------------------------------------------------------
//Atmega16 IDE AVR studio4.18#include "avr/interrupt.h"
#include "avr/iom16.h"
#include "avr/io.h"
const unsigned char _7_seg[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xd8,0x80,0x90,0xff };
unsigned char time_cnt,min_cnt=43,hour_cnt=12,show_time=0;
unsigned char _1_sec_cnt=0x28 ; //一秒 計時
unsigned char scan_cnt=0X00; //顯示掃瞄的位數指標
unsigned char disp_0,disp_1,disp_2,disp_3;
//USER_FLAG_a------------------
unsigned char flag_a=0x00;
unsigned char _05sec=1;
#define _ONE_OFF PORTB|=_BV(4) //個
#define _ONE_ON PORTB&=~_BV(4)
#define _TWO_OFF PORTB|=_BV(3) //拾
#define _TWO_ON PORTB&=~_BV(3)
#define _THREE_OFF PORTB|=_BV(2) //百
#define _THREE_ON PORTB&=~_BV(2)
#define _FOUR_OFF PORTB|=_BV(1) //千
#define _FOUR_ON PORTB&=~_BV(1)
ISR (TIMER0_OVF_vect)
{
TCNT0 = 0x3D; //reload counter value
_1_sec_cnt -- ;
if (_1_sec_cnt==0) // 計算 1秒
{ time_cnt ++ ;
_1_sec_cnt=0x28 ;
}
if(_1_sec_cnt>=0x14) // 產生0.5 Sec
{ flag_a|=_BV(_05sec);}
else
{flag_a&=~_BV(_05sec);}
if (time_cnt>=60) //每60秒進一
{ min_cnt+=1;
time_cnt=0;
}
if (min_cnt>=60) //每60分進一
{ hour_cnt+=1;
min_cnt=0;
}
}
void timer0_init(void)
{
TCCR0 = 0x00; //stop
TCNT0 = 0x3D; //set count
OCR0 = 0xC3; //set compare
TCCR0 = 0x05; //start timer
}
int main(void)
{
DDRA=0Xff;
PORTA=0Xff;
DDRB=0Xff;
PORTB=0Xff;
//stop errant interrupts until set up
cli(); //disable all interrupts
timer0_init();
MCUCR = 0x00;
GICR = 0x00;
TIMSK = 0x01; //timer interrupt sources
sei(); //re-enable interrupts
//all peripherals are now initialized
while (1)
{
if (scan_cnt>3) scan_cnt=0x00;
switch(scan_cnt)
{case 0:
PORTA=0XFF;
_ONE_ON;
_TWO_OFF;
_THREE_OFF;
_FOUR_OFF;
if (bit_is_set(flag_a,_05sec)) {PORTA= _7_seg[disp_0]&0x7f;}
else {PORTA= _7_seg[disp_0]|0x80;}
// PORTA= _7_seg[disp_0] ;
scan_cnt ++ ;
break;
case 1:
PORTA=0XFF;
_ONE_OFF;
_TWO_ON;
_THREE_OFF;
_FOUR_OFF;
if (bit_is_set(flag_a,_05sec)) {PORTA= _7_seg[disp_1]&0x7f;}
else {PORTA= _7_seg[disp_1]|0x80;}
// led_segment= _7_seg[disp_1] ;
scan_cnt ++ ;
break;
case 2:
PORTA=0XFF;
_ONE_OFF;
_TWO_OFF;
_THREE_ON;
_FOUR_OFF;
PORTA= _7_seg[disp_2] ;
scan_cnt ++ ;
break;
case 3:
PORTA=0XFF;
_ONE_OFF;
_TWO_OFF;
_THREE_OFF;
_FOUR_ON;
PORTA= _7_seg[disp_3] ;
scan_cnt ++ ;
break;
}
disp_0 = time_cnt % 10 ;
disp_1 = (time_cnt/10)%10 ;
disp_2= (min_cnt%10);
disp_3 = (min_cnt/10)%10 ;
}
}
//-------------------------------------------------------------------------------
//新唐 Cortex M0 NUC100 IDE MDK KEIL 4.2
#include
#include "NUC1xx.h"
#include "Driver\DrvGPIO.h"
#include "Driver\DrvSYS.h"
#define led_segment GPB_DOUT
#define _ONE GPIOA->DOUT.DOUT4 //個
#define _TWO GPIOA->DOUT.DOUT5 //拾
#define _THREE GPIOA->DOUT.DOUT6 //百
#define _FOUR GPIOA->DOUT.DOUT7 //千
#define BIBI DOUT8
#define ON_BIBI GPIOB->DOUT.BIBI=0
#define OFF_BIBI GPIOB->DOUT.BIBI=1
#define KEY0 PIN15
const char _7_seg[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xd8,0x80,0x90,0xff };
unsigned char time_cnt,min_cnt=43,hour_cnt=12,show_time=0;
unsigned char _1_sec_cnt=0x28 ; //一秒 計時
unsigned char scan_cnt=0X00; //顯示掃瞄的位數指標
unsigned char disp_0,disp_1,disp_2,disp_3;
typedef struct
{
struct
{
__IO uint32_t bibi_1:1;
__IO uint32_t _05sec:1;
__IO uint32_t hour_sw:1;
__I uint32_t RESERVE:29;
} Config;
} UART_FLAG_T;
UART_FLAG_T User1;
// User1.Config.hit_one = 1;
signed char dump_num=0,bi_time=5;
unsigned char cnt0=0,cnt1=0,cnt2=0,auto_hit=0;
unsigned char cnt02=0,cnt12=0,cnt22=0,auto_hit2=0;
volatile uint32_t FLAG_0=0;
void TMR0_IRQHandler(void) // Timer0 interrupt subroutine
{
TIMER0->TISR.TIF =1;
////////////////////////////////////////
if (User1.Config.bibi_1==1)
{ bi_time--;
if(bi_time<=0)
{User1.Config.bibi_1=0;
bi_time=5;
OFF_BIBI ;
}
else
{ON_BIBI; }
}
_1_sec_cnt -- ;
if (_1_sec_cnt==0) // 計算 1秒
{ time_cnt ++ ;
_1_sec_cnt=0x28 ;
}
if(_1_sec_cnt>=0x14) // 產生0.5 Sec
{User1.Config._05sec=1;}
else {User1.Config._05sec=0;}
if (time_cnt>=60) //每60秒進一
{ min_cnt+=1;
time_cnt=0;
}
if (min_cnt>=60) //每60分進一
{ hour_cnt+=1;
min_cnt=0;
}
// TIMER0->TISR.TIF =1;
}
//
void Timer_initial(void)
{
/* Step 1. Enable and Select Timer clock source */
/* 切換IP模組的時鐘源 */
SYSCLK->CLKSEL1.TMR0_S = 0; //Select 12Mhz for Timer0 clock source
SYSCLK->APBCLK.TMR0_EN =1; //Enable Timer0 clock source
/* Step 2. Select Operation mode */
TIMER0->TCSR.MODE=1; //Select periodic mode for operation mode
/* Step 3. Select Time out period = (Period of timer clock input) * (8-bit Prescale + 1) * (24-bit TCMP)*/
TIMER0->TCSR.PRESCALE=0; // Set Prescale [0~255]
TIMER0->TCMPR = 300000 ; // Set TICR(TCMP) [0~16777215]
// (1/12000000)*(0+1)*(300000)= 250usec
/* Step 4. Enable interrupt */
TIMER0->TCSR.IE = 1;
TIMER0->TISR.TIF = 1; //Write 1 to clear for safty
NVIC_EnableIRQ(TMR0_IRQn); //Enable Timer0 Interrupt
/* Step 5. Enable Timer module */
TIMER0->TCSR.CRST = 1; //Reset up counter
TIMER0->TCSR.CEN = 1; //Enable Timer0
TIMER0->TCSR.TDR_EN=1; //
}
/*-----------*/
/* Main Function */
/*-----------*/
int main(void)
{
//volatile int32_t i32delay=1000;
/* SYSCLK =>12Mhz*/
UNLOCKREG();
SYSCLK->PWRCON.XTL12M_EN = 1 ;
while(SYSCLK->CLKSTATUS.XTL12M_STB==0);
SYSCLK->CLKSEL0.HCLK_S=0;
SYSCLK->CLKSEL0.STCLK_S=0;
//------------------------------------
GPIOA-> PMD.PMD4 = 0X03; // 設為雙向,和51_IO 相同
GPIOA-> PMD.PMD5 = 0X03; // 設為雙向,和51_IO 相同
GPIOA-> PMD.PMD6 = 0X03; // 設為雙向,和51_IO 相同
GPIOA-> PMD.PMD7 = 0X03; // 設為雙向,和51_IO 相同
GPIOB-> PMD.PMD0 = 0X03; // 設為雙向,和51_IO 相同
GPIOB-> PMD.PMD1 = 0X03; // 設為雙向,和51_IO 相同
GPIOB-> PMD.PMD2 = 0X03; // 設為雙向,和51_IO 相同
GPIOB-> PMD.PMD3 = 0X03; // 設為雙向,和51_IO 相同
GPIOB-> PMD.PMD4 = 0X03; // 設為雙向,和51_IO 相同
GPIOB-> PMD.PMD5 = 0X03; // 設為雙向,和51_IO 相同
GPIOB-> PMD.PMD6 = 0X03; // 設為雙向,和51_IO 相同
GPIOB-> PMD.PMD7 = 0X03; // 設為雙向,和51_IO 相同
//--設定time0 啟動time0中斷
Timer_initial();
//--設定time0 啟動time0中斷
GPB_DMASK=0xff00;
User1.Config.bibi_1=0;
while (1)
{
if (scan_cnt>3) scan_cnt=0x00;
switch(scan_cnt)
{case 0:
led_segment=0XFF;
_ONE=0x00;
_TWO=0x01;
_THREE=0X01;
_FOUR=0X01;
if(User1.Config._05sec==1){led_segment= _7_seg[disp_0]&0x7f;} //
else {led_segment= _7_seg[disp_0]|0x80;}
// led_segment= _7_seg[disp_0] ;
scan_cnt ++ ;
break;
case 1:
led_segment=0XFF;
_ONE=0x01;
_TWO=0x00;
_THREE=0X01;
_FOUR=0X01;
if(User1.Config._05sec==1){led_segment= _7_seg[disp_1]&0x7f;} //
else {led_segment= _7_seg[disp_1]|0x80;}
// led_segment= _7_seg[disp_1] ;
scan_cnt ++ ;
break;
case 2:
led_segment=0XFF;
_ONE=0x01;
_TWO=0x01;
_THREE=0X00;
_FOUR=0X01;
led_segment= _7_seg[disp_2] ;
scan_cnt ++ ;
break;
case 3:
led_segment=0XFF;
_ONE=0x01;
_TWO=0x01;
_THREE=0X01;
_FOUR=0X00;
led_segment= _7_seg[disp_3] ;
scan_cnt ++ ;
break;
}
disp_0 = time_cnt % 10 ;
disp_1 = (time_cnt/10)%10 ;
disp_2= (min_cnt%10);
disp_3 = (min_cnt/10)%10 ;
}
}
Good~ 新唐那顆100的設定不會很麻煩嗎?
回覆刪除其實不會麻煩,通常在跨平台的時候,會遇到的就是,它的外設設定的不同,可以一步一步切入,如先從系統時鐘設定了解,之後再GPIO設定,TIMER設定,一步一步來,沒用到的先不要管它
刪除作者已經移除這則留言。
回覆刪除