// CLOCK-CONT // CL*-LCD 2013-6-3 // ATmega644 でRTC8564のコントロール // ------------------------------------------------- // ATmega644 Xtal =10M // Lo=F7 Hi=DF Ex=FF   // // PC0=SCL PC1=SDA // // LCD SC2004 // DB4=D4,DB5=D5,DB6=D6,DB7=D7, RS=D1 E=D0 // //---------------------------------------------------- // // RTC 400kHz // TWI設定 SCL周波数=CPUクロック/16+2*TWBR*分周 // // TWBR= 10000-000/50000(SCL50k)-16 / 2*1 // = 92 //---------------------------------------------------- // マスタ動作 送信受信を切り替える // TWIアクノーリッジ ACK NACK // //---------------------------------------------------- // #include #define F_CPU 10000000UL //10M #include #include #include // 擬似命令 #define LED_GON PORTB |= _BV(PB0) #define LED_GOFF PORTB &=~_BV(PB0) #define LED_RON PORTB |= _BV(PB1) #define LED_ROFF PORTB &=~_BV(PB1) #define LCD_E_on PORTD |= _BV(PD0) #define LCD_E_off PORTD &=~_BV(PD0) #define LCD_RS_on PORTD |= _BV(PD1) #define LCD_RS_off PORTD &=~_BV(PD1) #define KEY_MENU bit_is_clear (PINC ,PC7) #define KEY_MENU_OFF bit_is_set (PINC ,PC7) #define KEY_RET bit_is_clear (PINC ,PC6) #define KEY_RET_OFF bit_is_set (PINC ,PC6) #define KEY_CAN bit_is_clear (PINC ,PC5) #define KEY_CAN_OFF bit_is_set (PINC ,PC5) #define KEY_LEFT bit_is_clear (PINC ,PC4) #define KEY_RIGHT bit_is_clear (PINC ,PC3) #define RTC_ADDR_WRITE 0xA2 #define RTC_ADDR_READ 0XA3 #define I2C_BPS 92 //SCL通信速度 TWBR=92 volatile uint8_t aux_d[60]; //書込データ volatile uint8_t w_data[10]; //書込データ volatile uint8_t r_data[10]; //読込データ //---------------------------------------------- enum eSAVE { MP1,MP2,MP3,MP4, }; //--------------------------------------------- const char *datweek[7] ={ "Sun","Mon","Tue","Wed","Thu","Fri","Sat", }; //------------------------------------------------ uint8_t ren_count; //USART data uint8_t hop_count; //USART data uint8_t dat1; uint8_t dsec; int8_t sec; uint8_t dmin; int8_t min; uint8_t dhour; int8_t hour; uint8_t dday; int8_t day; uint8_t dmonth; int8_t month; uint8_t dyear; int16_t year; uint8_t dweek; int8_t week; uint8_t com; uint8_t ans; uint8_t dat16; uint8_t dat10; uint8_t wdat; //*---------------timer----------------------------- void wait_ms(uint16_t m ) //1=1ms { while(m--) _delay_ms(1); } //----- void wait_us(uint16_t m ) //1=1us { while(m--) _delay_us(1); } // ******* 書き込み 方法 ********************* // eeprom_busy_wait(); eeprom_write_byte((uint8_t*)MP1,cou1); // // /*-----------------------------------------------------------*/ /* LCD初期化  RS=0 --> data --> RS=1 */ /*-----------------------------------------------------------*/ void lcd_init(void) { wait_ms(100); //100ms LCD_RS_off; // RS=0 set // 1---0011 0000 lcd_put_4bit(0x30); wait_ms(10); //10ms // 2---0011 0000 lcd_put_4bit(0x30); wait_ms(10); // 3---0011 0000 lcd_put_4bit(0x30); wait_ms(1); //1ms /// 4---0010 0000 lcd_put_4bit(0x20); // 5---0010 1000 lcd_put_8bit(0x28); /* Mode=4bit / Line=2 / Font=5x7dot*/ // 6---0000 1000 lcd_put_8bit(0x08); /* 表示OFF */ // 7---0000 0001 lcd_put_8bit( 0x01 ); /* Display Clear*/ // 8---0000 0110 lcd_put_8bit( 0x06 ); /* entry mode set*/ // 9---0000 1100 lcd_put_8bit( 0x0C ); /* disply on*/ LCD_RS_on; /* RS = H */ } /*-----------------------------------------------------------*/ /* LCD 4ビット送信 */ /* 引数: char bitdata : DB7-4に与えるデータ */ /* DB4=D4 DB5=D5 DB6 = D6 DB7=D7 */ /* RS=D2 E=D3 */ /*-----------------------------------------------------------*/ void lcd_put_4bit(char bitdata) { // bitdata=bitdata >> 4; /*上位-->下位へ移動 */ bitdata=bitdata & 0xF0; /* 0000 1111 & */ unsigned char rdata; rdata = PIND; rdata=rdata & 0x0F; /*portD and 0b1111 0000 */ unsigned char portdata; portdata=(bitdata | rdata); /* OR */ PORTD = portdata; /* portdata 出力 */ LCD_E_off; // E=0 wait_ms(1); //1ms timer LCD_E_on; // E=1 wait_ms(1); //1ms timer } /*-----------------------------------------------------------*/ /* LCD 8ビット送信 */ /*-----------------------------------------------------------*/ void lcd_put_8bit(char chdat) { lcd_put_4bit(chdat); /* 上位 4bit */ lcd_put_4bit(chdat << 4); /* 下位 4bit を(左)上位シフト */ } /*-----------------------------------------------------------*/ /* LCD 文字列表示 */ /* 引数: char *str : 文字列の先頭ポインタ */ /*-----------------------------------------------------------*/ void lcd_put_str(char *str) { while(*str != 0) { lcd_put_8bit( *str ); str++; } } /*-----------------------------------------------------------*/ /* LCD表示位置の設定 */ /* 引数:char tx :x座標 */ /* 引数:char ty :y座標 */ /* 戻り値:なし */ /* tx */ /* 0123456789ABCDEF */ /* ty 0################ */ /* 1################ */ /* 2################ */ /* 3################ */ /*-----------------------------------------------------------*/ void lcd_position(char tx ,char ty) { switch(ty){ case 0: ty = 0x00; break; case 1: ty = 0x40; break; case 2: ty = 0x14; break; case 3: ty = 0x54; break; } LCD_RS_off; // RS=0 set lcd_put_8bit(0x80 | (tx + ty)); /* Address = 0 */ LCD_RS_on; /* RS = H */ } /*-----------------------------------------------------------*/ void LCD_dataout( unsigned short data ) // 数値データをLCDに表示する関数) { // 表示出来る数値は 受け取る引数unsigned short dataのデータ型範囲 unsigned char temp; // unsigned char :( 0-255), unsigned short:(0-65535), unsigned long :(0-4294967295) char strtemp[ 5 ]; // 文字コードの格納変数を定義 int i, k; // 受け取る引数 " unsigned char "data のデータ型を変更すると strtemp[ 配列数 ] 配列数 を変えましょう i=0; // unsigned charのとき:strtemp[ 3 ] (3桁), unsigned short:strtemp[ 5 ](5桁) , unsigned long:strtemp[ 10 ](10桁) do { // temp = data % 10; // 下位の桁から数字を抽出 strtemp[i++] = temp + '0'; // 数字を文字コードに変換 } while (( data /= 10 ) != 0); // 数値の桁数までループ i--; // for( k=i; k>=0; k-- ) { // 上位の桁から順次 lcd_put_8bit( strtemp[k]); // 数値文字を表示 } // } /* --------- ASC -------------------------------*/ void LCD_ASC(unsigned short data ) // ASC 表示 { unsigned char temp; unsigned char temp1; temp1 = data & 0x0F; temp = data >> 4; if(temp > 9){temp=temp-9,(temp |= 0x40); }else{(temp |= 0x30);} if(temp1 > 9){temp1=temp1-9,(temp1 |= 0x40); }else{(temp1 |= 0x30);} lcd_put_8bit(temp); lcd_put_8bit(temp1); } // ------ COMMand -------------- // com ---> TWDR (0x02=sec, 0x03=min,0x04=hour,,,) // TWDR ---> ans void COM_READ(void) { /* 開始条件送出*/ TWCR = (1< sec(0F) void CRT_TIME(void) { sec =((dsec >> 4) & 0x07)*10 + (dsec & 0x0F); min =((dmin >> 4) & 0x07)*10 + (dmin & 0x0F); hour =((dhour >> 4) & 0x03)*10 + (dhour & 0x0F); day =((dday >> 4) & 0x03)*10 + (dday & 0x0F); week = dweek & 0x07; month =((dmonth >> 4) & 0x01)*10 + (dmonth & 0x0F); year =((dyear >> 4) & 0x0F)*10 + (dyear & 0x0F); } //--- TIME SET ------------------- void SET_TIME(void) { // ---year ------------- lcd_position(0,1); lcd_put_str("YEAR=20 "); lcd_position(7,1); LCD_dataout(year); while(1){ if(KEY_LEFT){year--; if(year < 0 ){year=99;} lcd_position(7,1); lcd_put_str(" "); lcd_position(7,1); LCD_dataout(year); wait_ms(300); } if(KEY_RIGHT){year++; if(year > 99){year=0;} lcd_position(7,1); LCD_dataout(year); wait_ms(300); } if(KEY_RET){ dat16=year; henkan10(); // dat16 --->dat10 変換する w_data[8]=dat10; //year break; } } if(KEY_RET){ } wait_ms(300); // ---- month --------------- lcd_position(0,1); lcd_put_str("Month= "); lcd_position(6,1); LCD_dataout(month); while(1){ if(KEY_LEFT){month--; if(month < 1){month=12;} lcd_position(6,1); lcd_put_str(" "); lcd_position(6,1); LCD_dataout(month); wait_ms(300); } if(KEY_RIGHT){month++; if(month > 12){month=1;} lcd_position(6,1); LCD_dataout(month); wait_ms(300); } if(KEY_RET){ dat16=month; henkan10(); w_data[7]=dat10; break; } } if(KEY_RET){ } wait_ms(300); // ---- day --------------- lcd_position(0,1); lcd_put_str("Day= "); lcd_position(4,1); LCD_dataout(day); while(1){ if(KEY_LEFT){day--; if(day < 1){day=31;} lcd_position(4,1); lcd_put_str(" "); lcd_position(4,1); LCD_dataout(day); wait_ms(300); } if(KEY_RIGHT){day++; if(day > 31){day=1;} lcd_position(4,1); LCD_dataout(day); wait_ms(300); } if(KEY_RET){ dat16=day; henkan10(); w_data[5]=dat10; break; } } if(KEY_RET){ } wait_ms(300); // ---- day --------------- lcd_position(0,1); lcd_put_str("Hour= "); lcd_position(5,1); LCD_dataout(hour); while(1){ if(KEY_LEFT){hour--; if(hour < 0){hour=23;} lcd_position(5,1); lcd_put_str(" "); lcd_position(5,1); LCD_dataout(hour); wait_ms(300); } if(KEY_RIGHT){hour++; if(hour > 23){hour=0;} lcd_position(5,1); LCD_dataout(hour); wait_ms(300); } if(KEY_RET){ dat16=hour; henkan10(); w_data[4]=dat10; break; } } if(KEY_RET){ } wait_ms(300); // ---- day --------------- lcd_position(0,1); lcd_put_str("Min = "); lcd_position(5,1); LCD_dataout(min); while(1){ if(KEY_LEFT){min--; if(min < 0){min=59;} lcd_position(5,1); lcd_put_str(" "); lcd_position(5,1); LCD_dataout(min); wait_ms(300); } if(KEY_RIGHT){min++; if(min > 59){min=0;} lcd_position(5,1); LCD_dataout(min); wait_ms(300); } if(KEY_RET){ dat16=min; henkan10(); w_data[3]=dat10; break; } } if(KEY_RET){ } lcd_position(0,1); lcd_put_str(" "); wait_ms(300); INIT_TIME(); } //---- 16進ーー>10進変換--------- // dat16 のデータを 10進に変換し dat10 に戻す。 void henkan10(void) { dat10 = ((dat16 / 10) << 4) | (dat16 % 10); } /*-----------------------------------------------------------*/ int main () { //初期化 出力=1 入力=0 DDRA = 0x00; // 0b0000-0000 全IN DDRB = 0x03; // 0b0000-0011 DDRC = 0x00; // 0b0000-0000 DDRD = 0xF3; // 0b1111-0011 PORTA = 0x00; // pul up PORTC = 0x00; // H 出力 PORTB = 0x00; // PORTD = 0x00; // H 出力 //------------ LCD INIT ----------------- lcd_init(); //--------------------------------------- lcd_position(0,1); lcd_put_str("ATMEGA64 majima"); lcd_position(0,0); lcd_put_str("CLOCK CL1-LCD "); lcd_position(0,3); lcd_put_str("Ver 2 "); LED_GON; wait_ms(300); LED_GOFF; wait_ms(300); LED_GON; wait_ms(300); LED_GOFF; wait_ms(300); LED_GON; //--------------------------------------------- // SCL=10M/(16+ 2*47*1)=200kHz TWBR=47; TWSR=0x00; //ビット速度値 TWCR=0b00000100; // TWI SCL/SDA で使用する while(1){ LED_RON; LED_GOFF; READ_TIME(); // RTC 時刻読取 --->dyear-dsec LED_ROFF; LED_GON; CRT_TIME(); lcd_position(0,2); lcd_put_str("20"); lcd_position(2,2); LCD_ASC(dyear); lcd_position(4,2); lcd_put_str("/"); LCD_ASC(dmonth); lcd_put_str("/"); LCD_ASC(dday); lcd_position(0,3); LCD_ASC(dhour); lcd_position(2,3); lcd_put_str(":"); LCD_ASC(dmin); lcd_put_str(":"); LCD_ASC(dsec); lcd_position(15,3); lcd_put_str(datweek[week]); if(KEY_MENU){SET_TIME();} } //while(1)終了 return 0; }