2014年3月11日 星期二

趨勢

很久以前曾購買"時鐘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 ; 
                     
  }
 }

3 則留言:

  1. Good~ 新唐那顆100的設定不會很麻煩嗎?

    回覆刪除
    回覆
    1. 其實不會麻煩,通常在跨平台的時候,會遇到的就是,它的外設設定的不同,可以一步一步切入,如先從系統時鐘設定了解,之後再GPIO設定,TIMER設定,一步一步來,沒用到的先不要管它

      刪除
  2. 作者已經移除這則留言。

    回覆刪除