![]()

LCDはブルーバックライトのSC1601Aを使う
ピン配置は 2行、4行シリーズと同じ配置なので、プログラムも同じに使える
注意は
1行の16桁あるのだが、 1行目は 8桁で 9桁〜16桁は 2行として使う
行制御のプログラムを変更してもよいのだが、
同じで使えるので、8桁として使う
RTCにRX8900を使う
高精度 DXCXOを搭載して 月差を10秒位になっている
![]()
![]()
プログラム
//
// ATmega328 でSC1601 LCDのコントロールと
// RTC8900のテストコントロール
// -------------------------------------------------
// ATmega328 Xtal =8M
// Lo=E2 Hi=DF Ex=FF
//
// PC5=SCL PC4=SDA
//
// LCD SC1601A
// DB4=D4,DB5=D5,DB6=D6,DB7=D7, RS=D0 E=D1
//
//----------------------------------------------------
//
// RTC 400kHz
// TWI設定 SCL周波数=CPUクロック/16+2*TWBR*分周
//
// TWBR= 10000-000/50000(SCL50k)-16 / 2*1
// = 92
#include <avr/io.h>
#define F_CPU 8000000UL //内部8M
#include <avr/delay.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
// 擬似命令
#define LED_RON PORTD |= _BV(PD2)
#define LED_ROFF PORTD &=~_BV(PD2)
#define LCD_E_on PORTD |= _BV(PD1)
#define LCD_E_off PORTD &=~_BV(PD1)
#define LCD_RS_on PORTD |= _BV(PD0)
#define LCD_RS_off PORTD &=~_BV(PD0)
#define KEY_MENU bit_is_clear (PINB ,PB0)
#define KEY_RET bit_is_clear (PINB ,PB1)
#define KEY_LEFT bit_is_clear (PINB ,PB6)
#define KEY_RIGHT bit_is_clear (PINB ,PB2)
#define RTC_ADDR_WRITE 0x64
#define RTC_ADDR_READ 0X65
#define I2C_BPS 92 //SCL通信速度 TWBR=92
volatile uint8_t r_flg[10]; //書込データ
volatile uint8_t w_data[20]; //書込データ
volatile uint8_t r_data[20]; //読込データ
//----------------------------------------------
enum eSAVE
{
MP1,MP2,MP3,MP4,
};
//---------------------------------------------
const char *datweek[7] ={
"Sun","Mon","Tue","Wed","Thu","Fri","Sat",
};
//------------------------------------------------
uint8_t count; //USART data
uint8_t count1; //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 week_cou;
uint8_t com;
uint8_t ans;
uint8_t dat16;
uint8_t dat15;
uint8_t dat10;
uint8_t wdat;
uint8_t dat_frg;
uint8_t tset_flg;
//*---------------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);
}
//-----------------------------
void RTC_RS(void)
{
/* 開始条件送出*/
TWCR = (1<<TWINT)|(1<<TWSTA) |(1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
TWDR=RTC_ADDR_WRITE; // 0b00110010; //64
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
TWDR=0x00;
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
/* 開始条件送出*/
TWCR = (1<<TWINT)|(1<<TWSTA) |(1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
TWDR=RTC_ADDR_READ; //0b00110011; //65
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
}
//---------------------
void RTC_RE(void)
{
/*DATA データ読込 */
TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
ans=TWDR; //データを取得
wait_ms(2);
}
//------------------------
void RTC_STOP(void)
{
/* 停止条件送出*/
TWCR = (1<<TWINT)|(1<<TWSTO) |(1<<TWEN);
wait_us(100);
}
//---- READ TIME -------------
void READ_TIME(void)
{
int i;
RTC_RS();
for(i=0;i<12;i++){
RTC_RE();
r_data[i]=ans;
}
RTC_STOP();
dsec=r_data[0] & 0x7F;
dmin=r_data[1] & 0x7F;
dhour=r_data[2] & 0x3F;
dday=r_data[4] & 0x3F;
dweek=r_data[3] & 0x7F;
dmonth=r_data[5]& 0x1F;
dyear=r_data[6] & 0xFF;
}
//-----------------------------------
//-----------------------------
void RTC_FRG(void)
{
/* 開始条件送出*/
TWCR = (1<<TWINT)|(1<<TWSTA) |(1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
TWDR=RTC_ADDR_WRITE; // 0b00110010; //64
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
TWDR=0x1D;
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
/* 開始条件送出*/
TWCR = (1<<TWINT)|(1<<TWSTA) |(1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
TWDR=RTC_ADDR_READ; //0b00110011; //65
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
}
//---------------------
void RTC_FRE(void)
{
/*DATA データ読込 */
TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
ans=TWDR; //データを取得
wait_ms(50);
}
//-------------------------------------------------------
void read_frg(void)
{
int i;
RTC_FRG();
for(i=0;i<3;i++){
RTC_FRE();
r_flg[i]=ans;
}
RTC_STOP();
//com=0x00;
//wdat=0b00000000; //start
//RTC_WS();
//RTC_WE();
//RTC_STOP();
wait_ms(5000);
}
//----- WRITE TIME -------------
void RTC_DAT(void)
{
r_data[0] =0x00; //SEC
r_data[1] =0x00; //min
r_data[2] =0x00; //hour
r_data[3] =0x00; //week
r_data[4] =0x00; //day
r_data[5] =0x00; //month
r_data[6] =0x00; //year
r_data[7] =0x00; //ram
r_data[8] =0x00; //alam
}
//-----------------------------------------------------------
void RTC_WS(void)
{
/* 開始条件送出*/
TWCR = (1<<TWINT)|(1<<TWSTA) |(1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
TWDR=RTC_ADDR_WRITE; //64
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
TWDR=0x00;
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
}
//-----
void RTC_WE(void)
{
/*data 書込み*/
TWDR=wdat; //
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
}
//---- INIT TIME -------------
void RTC_INIT(void)
{
int i;
RTC_WS();
for(i=0;i<8;i++){
wdat=w_data[i];
RTC_WE();
}
RTC_STOP();
com=0x00;
wdat=0b00000000; //start
RTC_WS();
RTC_WE();
RTC_STOP();
}
//----- WRITE TIME -------------
void WRITE_DAT(void)
{
w_data[0] =0x20; //SEC
w_data[1] =0x00; //MIN
w_data[2] =0x00; //HOUR
w_data[3] =0x00; //WEEK
w_data[4] =0x00; //day
w_data[5] =0x00; //month
w_data[6] =0x00; //year
w_data[7] =0x00; //RAM
}
//---- INIT TIME -------------
void RTC_RESET(void)
{
int i;
RTC_SYOKI();
for(i=0;i<1;i++){
wdat=0;
RTC_WE();
}
RTC_STOP();
wait_ms(1000);
}
//-----------------------------------------------------------
void RTC_SYOKI(void)
{
/* 開始条件送出*/
TWCR = (1<<TWINT)|(1<<TWSTA) |(1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
TWDR=RTC_ADDR_WRITE; //64
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
TWDR=0x0E;
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))); //;TWINT=1まで待機
}
//---- CRT time --------------
// 10進 −−−>16進表示 dsec(15) --> 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);
month =((dmonth >> 4) & 0x01)*10 + (dmonth & 0x0F);
year =((dyear >> 4) & 0x0F)*10 + (dyear & 0x0F);
dweek=(dweek & 0x3F);
}
//--- TIME SET -------------------
void SET_TIME(void)
{
// ---year -------------
lcd_position(0,0);
lcd_put_str(" YEAR=20");
lcd_position(0,1);
lcd_put_str(" ");
lcd_position(0,1);
LCD_dataout(year);
while(1){
if(KEY_LEFT){year--;
if(year < 0 ){year=99;}
lcd_position(0,1);
lcd_put_str(" ");
lcd_position(0,1);
LCD_dataout(year);
wait_ms(300);
}
if(KEY_RIGHT){year++;
if(year > 99){year=0;lcd_position(0,1);
lcd_put_str(" ");}
lcd_position(0,1);
LCD_dataout(year);
wait_ms(300);
}
if(KEY_RET){
dat16=year;
henkan10(); // dat16 --->dat10 変換する
w_data[6]=dat10; //year
break;
}
}
if(KEY_RET){ }
wait_ms(300);
// ---- month ---------------
lcd_position(0,0);
lcd_put_str("Month= ");
lcd_position(0,1);
lcd_put_str(" ");
lcd_position(0,1);
LCD_dataout(month);
while(1){
if(KEY_LEFT){month--;
if(month < 1){month=12;}
lcd_position(0,1);
lcd_put_str(" ");
lcd_position(0,1);
LCD_dataout(month);
wait_ms(300);
}
if(KEY_RIGHT){month++;
if(month > 12){month=1;lcd_position(0,1);
lcd_put_str(" ");}
lcd_position(0,1);
LCD_dataout(month);
wait_ms(300);
}
if(KEY_RET){
dat16=month;
henkan10();
w_data[5]=dat10;
break;
}
}
if(KEY_RET){ }
wait_ms(300);
// ---- day ---------------
lcd_position(0,0);
lcd_put_str("Day= ");
lcd_position(0,1);
lcd_put_str(" ");
lcd_position(0,1);
LCD_dataout(day);
while(1){
if(KEY_LEFT){day--;
if(day < 1){day=31;}
lcd_position(0,1);
lcd_put_str(" ");
lcd_position(0,1);
LCD_dataout(day);
wait_ms(300);
}
if(KEY_RIGHT){day++;
if(day > 31){day=1;lcd_position(0,1);
lcd_put_str(" ");}
lcd_position(0,1);
LCD_dataout(day);
wait_ms(300);
}
if(KEY_RET){
dat16=day;
henkan10();
w_data[4]=dat10;
break;
}
}
if(KEY_RET){ }
wait_ms(300);
// ---- hour ---------------
lcd_position(0,0);
lcd_put_str("Hour= ");
lcd_position(0,1);
lcd_put_str(" ");
lcd_position(0,1);
LCD_dataout(hour);
while(1){
if(KEY_LEFT){hour--;
if(hour < 0){hour=23;}
lcd_position(0,1);
lcd_put_str(" ");
lcd_position(0,1);
LCD_dataout(hour);
wait_ms(300);
}
if(KEY_RIGHT){hour++;
if(hour > 23){hour=0; lcd_position(0,1);
lcd_put_str(" ");}
lcd_position(0,1);
LCD_dataout(hour);
wait_ms(300);
}
if(KEY_RET){
dat16=hour;
henkan10();
w_data[2]=dat10;
break;
}
}
if(KEY_RET){ }
wait_ms(300);
// ---- min ---------------
lcd_position(0,0);
lcd_put_str("Min = ");
lcd_position(0,1);
lcd_put_str(" ");
lcd_position(0,1);
LCD_dataout(min);
while(1){
if(KEY_LEFT){min--;
if(min < 0){min=59;}
lcd_position(0,1);
lcd_put_str(" ");
lcd_position(0,1);
LCD_dataout(min);
wait_ms(300);
}
if(KEY_RIGHT){min++;
if(min > 59){min=0;lcd_position(0,1);
lcd_put_str(" ");}
lcd_position(0,1);
LCD_dataout(min);
wait_ms(300);
}
if(KEY_RET){
dat16=min;
henkan10();
w_data[1]=dat10;
break;
}
}
if(KEY_RET){ }
lcd_position(0,0);
lcd_put_str(" ");
wait_ms(300);
// ----weekn ---------------
lcd_position(0,0);
lcd_put_str("Week = ");
lcd_position(0,1);
lcd_put_str(" ");
lcd_position(0,1);
LCD_dataout(week);
while(1){
if(KEY_LEFT){week--;
if(week < 0){week=7;}
lcd_position(0,1);
lcd_put_str(" ");
lcd_position(0,1);
LCD_dataout(week);
wait_ms(300);
}
if(KEY_RIGHT){week++;
if(week > 8){week=1;lcd_position(0,1);
lcd_put_str(" ");}
lcd_position(0,1);
LCD_dataout(week);
wait_ms(300);
}
if(week == 1){dat15=0x01;}
if(week == 2){dat15=0x02;}
if(week == 3){dat15=0x04;}
if(week == 4){dat15=0x08;}
if(week == 5){dat15=0x10;}
if(week == 6){dat15=0x20;}
if(week == 7){dat15=0x40;}
if(KEY_RET){
w_data[3]=dat15;
break;
}
}
if(KEY_RET){ }
lcd_position(0,0);
lcd_put_str(" ");
lcd_position(0,1);
lcd_put_str(" ");
wait_ms(300);
RTC_INIT();
}
//---- 16進ーー>10進変換---------
// dat16 のデータを 10進に変換し dat10 に戻す。
void henkan10(void)
{
dat10 = ((dat16 / 10) << 4) | (dat16 % 10);
}
/*-----------------------------------------------------------*/
int main () {
//初期化 出力=1 入力=0
DDRB = 0x00; // 0b0000-0011
DDRC = 0x00; // 0b0000-0000
DDRD = 0xFF; // 0b1111-1111
PORTC = 0x00; // H 出力
PORTB = 0xFF; //
PORTD = 0x00; // H 出力
//------------ LCD INIT -----------------
lcd_init();
//---------------------------------------
lcd_position(0,0);
lcd_put_str("SC1601");
lcd_position(0,1);
lcd_put_str("RTC8900");
LED_RON;
wait_ms(300);
LED_ROFF;
wait_ms(300);
LED_RON;
wait_ms(300);
LED_ROFF;
wait_ms(300);
lcd_position(0,0);
lcd_put_str(" ");
lcd_position(0,1);
lcd_put_str(" ");
//---------------------------------------------
// SCL=10M/(16+ 2*47*1)=200kHz
TWBR=47;
TWSR=0x00; //ビット速度値
TWCR=0b00000100; // TWI SCL/SDA で使用する
//---------------------------------------
RTC_RESET();
lcd_position(10,1);
LCD_ASC(r_flg[0]);
LCD_ASC(r_flg[1]);
LCD_ASC(r_flg[2]);
LED_RON;
wait_ms(300);
LED_ROFF;
LED_RON;
wait_ms(300);
LED_ROFF;
LED_RON;
wait_ms(300);
LED_ROFF;
LED_RON;
wait_ms(300);
LED_ROFF;
tset_flg=0;
while(1){
if (tset_flg == 1){
READ_TIME(); // RTC 時刻読取 --->dyear-dsec
CRT_TIME();
tset_flg=0;
}
lcd_position(1,0);
LCD_ASC(dmonth);
lcd_put_str("/");
LCD_ASC(dday);
lcd_position(1,1);
LCD_ASC(dhour);
lcd_put_str(":");
LCD_ASC(dmin);
if(KEY_MENU){SET_TIME();}
count=count+1;
if (count == 40){tset_flg=1;LED_RON;wait_ms(500);}
wait_ms(1000);
LED_ROFF;
} //while(1)終了
return 0;
}
![]()