goo blog サービス終了のお知らせ 

JH7UBCブログ

アマチュア無線 電子工作 家庭菜園など趣味のブログです

PIC16F1705 MCC シリアル通信テスト

2022-04-01 14:36:48 | MPLAB X MCC
 MPLAB X + XC8 + MCCの環境でPIC16F1705のシリアル通信テストをします。
 USBシリアル変換は、秋月電子のFT234モジュールを利用し、PIC16F1705のシリアル通信ポートはデフォルトで、RC4=TX,RC5=RXとします。
 回路図です。PIC16F1705の電源は、FT234からの5Vを利用します。


 プロジェクトを作成し、MCCを立ち上げます。
 System Moduleの設定です。
 Clockは、INTOSC,FOSC,8MHz_HF,PLL Enableとし、32MHzで動作させています。

 EUSARTを導入すると、デフォルトで、RC4=TX,RC5=RXになっています。
 Pin Moduleです。RC4のOutputは最初からチェックが入っています。Analogのチェックは入れても入れなくとも動作するようです。

 EUSART Moduleの設定です。Baud Rateは、デフォルトの9600bpsのままです。他の設定もデフォルトのままです。

 動作確認のために、簡単なエコーバックテストを行いました。 
 プログラムリストです。
------------------------------------------------------------------------
/*
 * PIC16F1705 MCC Serial通信テスト
 * 2022.4.1
 * JH7UBC Keiji Hata
 */

#include "mcc_generated_files/mcc.h"

void main(void)
{
     // initialize the device
     SYSTEM_Initialize();
     uint8_t data;
     while (1)
    {
         data = EUSART_Read();
         EUSART_Write(data);
    }
}
------------------------------------------------------------------------
 ブレッドボードです。

 パソコンと接続して、TeraTermと通信させます。
 パソコンのキーボードで文字を打つと、エコーバックされ、TeraTermに表示されました。

 PIC16F1705では、PPS(Peripheral Pin Select)機能により、任意のPinにTX,RXを設定することができます。

 例えば、RA0=TX,RA1=RXとするには、MCCのPin Managerで下の図のように指定すれば、OKです。プログラムは変更なしで、FT234とPIC16F1705のTX,RXの配線の変更だけで、シリアル通信ができます。



PIC16F1705 MCC LED Blink

2022-03-31 19:18:46 | MPLAB X MCC
 Raspberry Pi Picoの勉強が一段落しましたので、PICの勉強を再開します。

 対象とするPICは、PIC16F1705です。このPICについては、2019年にMPLAB X + XC8で様々テストをして、このブログとJH7UBCホームページに掲載しました。

 PIC16F1705の特徴は、PPS(Peripheral Pin Select)、DAC、オペアンプ内蔵などですが、設定はけっこう面倒です。今回は、MCC(MPLAB X Code Configurator)を利用して、各種テストをやってみることにします。

 まず、定番のLチカ(LED点滅)をやってみましょう。RC3にLEDを接続して、点滅させます。回路図です。



 MPLAB X + XC8でプロジェクトを作り、MCCを立ち上げます。
 System Moduleです。Clockは、INTOSC,FOSC,8MHz_HF,PLL Enableとし、32MHz(最高速)としました。
 Low-Voltage Programming Enableのチェックを外し、RC3を出力に設定します。



 Pin Moduleの設定です。



 プログラムリストです。非常に簡単です。
-------------------------------------------------------------
/*
 * PIC16F1705 MCC LED Blink
 * 2022.03.31
 * JH7UBC Keiji Hata  
*/

#include "mcc_generated_files/mcc.h"

void main(void)
{
     // initialize the device
     SYSTEM_Initialize();

     while (1)
    {
         LATC3=1;
         __delay_ms(500);
         LATC3=0;
         __delay_ms(500);
    }
}
-------------------------------------------------------------
ブレッドボードです。0.5秒ごとにLEDが点滅します。



PIC16F18326 MCC OLED表示テスト

2021-10-20 15:31:20 | MPLAB X MCC
PICでのOLED表示テストは、PIC16F1827を使って以前に行い、このブログに掲載しました。記事はこちら

今回は、秋月電子から購入したOLED(0.96インチ 128×64ドット 580円)を使い、PIC16F18326でMPLAB X + MCCの環境で表示テストを行いました。

PICとOLED間は、I2C通信でコントロールとデータ送信を行います。PIC16F18326の動作を確認するために、LEDをRA0に接続して点滅させます。電源は乾電池2個(3V)とします。OLEDモジュール内にプルアップ抵抗があるので、I2Cのプルアップ抵抗は省略しています。

回路図です。

プロジェクトを作成して、MCCを立ち上げます。System moduleの設定をします。HFINTOSC 32MHzとし、Clock Dividerは1とし、最高速で動作させています。Low-voltage programingのチェックを外します。
I2Cは、MSSP1モジュールを導入したので、10番ピン(RC0)がSCL1に、9番ピン(RC1)がSDA1になります。RA0はoutputに設定します。

pin moduleです。


MSSP1moduleです。I2C 100KHzに設定しました。

MCCのI2Cでは、割込みを使いますので、interrupt moduleを設定します。

さて、プログラミングですが、JR3TGS局のサイトに掲載されているものをMCC用に改良して使わせていただきました。フォントもそのまま使わせていただきました。ありがとうございました。

MCCでは、i2c1_master_example.c内にある次のI2C関係関数を利用します。
1バイト(8bit)のデータを送信する関数
I2C1_Write1ByteRegister(i2c1_address_t address, uint8_t reg, uint8_t data)
2バイト(16bit)のデータを送信する関数
I2C1_Write2ByteRegister(i2c1_address_t address, uint8_t reg, uint16_t data)
Nバイトのデータを送信する関数
I2C1_WriteNBytes(i2c1_address_t address, uint8_t* data, size_t len)

font6.hとfont12.hは、Header ファイルとして、プロジェクトのヘッダフォルダに保存します。

以下、プログラムです。
printf()関数を使っていますので、projectのpropertiesで、XC8 Global OptionsのC standerdをC90にしてコンパイルします。
-------------------------------------------------------------------------------
/*
* PIC26F18326 MCC OLED
* 2021.10.20
* JH7UBC Keiji Hata
*/

#include "mcc_generated_files/mcc.h"
#include "mcc_generated_files/examples/i2c1_master_example.h"
#include "font6.h"
#include "font12.h"

#define OLED_addr 0x3C

uint8_t Page;
uint8_t Column;
uint8_t Low_col;
uint8_t Hi_col;
uint8_t Size;

uint8_t CLR_cmd[] ={0x00,0x20,0x00,0x21,0x00,0x7F,0x22,0x00,0x07};
//コマンド連続送信,Horizontal addredding Mode,column start address,
//column end address,page start address,page end address
uint8_t Posi_cmd[] = {0x00,0x20,0x02,0xB0,0x00,0x00};
//コマンド連続送信,Page addressing Mode,Page(B0-B7),low column,high column)
uint8_t Font6_data[] = {0x40,0x00,0x00,0x00,0x00,0x00,0x00};
//データ連続送信,font6データ6個
uint8_t Font12_data[] = {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
//データ連続送信,font12データ12個

//コマンド1byte送信
void OLED_cmd(uint8_t cmd){
I2C1_Write1ByteRegister(OLED_addr,0x80,cmd);
}

//データ1byte送信
void OLED_data(uint8_t dat){
I2C1_Write1ByteRegister(OLED_addr,0xC0,dat);
}

//OLED初期化
void OLED_init(){
OLED_cmd(0x8D); //Set charge pump
OLED_cmd(0x14); //Enable charge pump
OLED_cmd(0xAF); //Display ON
}

//OLED画面消去
void OLED_clr(){
I2C1_WriteNBytes(OLED_addr, CLR_cmd, 9);//Horizontal addressing mode
for(unsigned int i = 0;i < 1024 ;i++ ){ //0s00を1024個送信
OLED_data(0x00);
}
}

// 6x8dotフォントの表示開始位置指定
void font6_posi(uint8_t page, uint8_t column){
Size = 0; //printf で使用するputch のフォントサイズ指定
Page = page; // ページ情報をfont12用にグローバル変数に保存しておく
Column = column; // カラム情報をfont12用にグローバル変数に保存しておく
Posi_cmd[3] = 0xB0 + page; // ページ情報をコマンドにする為に 0xB0 を加算
Posi_cmd[4] = column & 0x0F; //low_column
column = column >>4;
Posi_cmd[5] = column + 0x10; //hi_column
I2C1_WriteNBytes(OLED_addr, Posi_cmd, 6); //Position コマンドをI2Cに送信
}

// 12x16dotフォントの表示開始位置指定
void font12_posi(uint8_t page,uint8_t column){
Size = 1; // printf で使用するputch のフォントサイズ指定
Page = page; // ページ情報をfont12用にグローバル変数に保存しておく
Column = column;// カラム情報をfont12用にグローバル変数に保存しておく
Posi_cmd[3] = page + 0xB0; // ページ情報をコマンドにする為に 0xB0 を加算
Posi_cmd[4] = column & 0x0F; //low_column
column = column >>4;
Posi_cmd[5] = column + 0x10; //hi_column
I2C1_WriteNBytes(OLED_addr, Posi_cmd, 6);
}

// 6x8dotフォントの1文字表示関数
void chr6(uint8_t c){
c = c - 0x20;
for(uint8_t i = 0; i<6; i++){
Font6_data[i+1] = font6[c][i];
}
I2C1_WriteNBytes(OLED_addr,Font6_data,7);
}

// 12x16dotフォントの1文字表示関数
void chr12(uint8_t c){
uint8_t temp;
uint8_t i;
c = c + 6 - 0x30;
Page = Page + 0xB0;
Low_col = Column & 0x0F;
temp = Column >> 4;
Hi_col = temp + 0x10;
Posi_cmd[3] = Page;
Posi_cmd[4] = Low_col;
Posi_cmd[5] = Hi_col;
I2C1_WriteNBytes(OLED_addr,Posi_cmd,6);
for(i = 0; i<12; i++){
Font12_data[i+1] = font12[c][i];
}
I2C1_WriteNBytes(OLED_addr,Font12_data,13);

Page = Page + 1;// グローバル変数ペーシ情報 Page を次の lower 12bytes 描画の為に 1 進める
Posi_cmd[3] = Page;
I2C1_WriteNBytes(OLED_addr,Posi_cmd,6);
for(i = 12; i<24; i++){
Font12_data[i-11] = font12[c][i];
}
I2C1_WriteNBytes(OLED_addr,Font12_data,13);
Page = Page - 1 - 0xB0;//グローバル変数ページ番号 Page を次の1文字描画の為、進めたページ番号を元に戻す (0xB0はコマンドをページ情報に戻す為)
Column = Column +12;// グローバル変数カラム情報を次の次の1文字描画の為、12アドレス進める
}

//printfで使用するputchの定義
void putch(uint8_t c){
if(Size){
chr12(c);
}else{
chr6(c);
}
}

void main(void)
{
// initialize the device
SYSTEM_Initialize();
// Enable the Global Interrupts
INTERRUPT_GlobalInterruptEnable();
// Enable the Peripheral Interrupts
INTERRUPT_PeripheralInterruptEnable();

OLED_init();
OLED_clr();

font6_posi(0,30);
printf("Hello World!");
font12_posi(2,0);
printf("0123456789");

while (1)
{
LATA0 = 1;
__delay_ms(500);
LATA0 = 0;
__delay_ms(500);
}
}

-------------------------------------------------------------------------------

ブレッドボードです。


PIC16F18326 AQM0802A表示テスト

2021-09-20 14:24:20 | MPLAB X MCC
 先月までPIC16F1827を利用して、MPLAB X + MCCでプログラムの勉強をしてきました。しかし、BME280(温度、湿度、気圧センサー)のデータを読み、処理する段階で浮動小数点計算が入ってきて、メモリ不足をおこしてしまいました。

 メモリ容量の大きいPICを探したら、PIC16F18326がありました。しかも安価(@140円)です。秋月電子から購入して、実験を始めました。まず、I2Cを利用したAQM0802Aの表示テストを行います。

 PIC16F18326の主なスペックです。
 最大クロック 32MHz
 プログラムメモリ 16kW
 EEPROM 256B
 RAM 2KB
 GPIO 12
 ADC 11ch
 DAC 1ch
 EUSART 1ch
 I2C 2ch
 SPI 2ch
 タイマ 7
 機能は多くありませんが、プログラムメモリが大きいのが特徴です。

 MPLAB Xでプロジェクトを作成し、MCCを立ち上げます。
 System moduleのセットをします。
 あれっ、PIC16F1827などの時と画面がちょっと違います。
 とりあえず、HFINTOSC,16MHz,Colck Divider=4,Low-voltage programingはoffとしました。

 PIC16F18326のドキュメントからクロックの説明図を見ると
 なるほど、オッシレータを選択して、その後にDividerが入っているんですね。なお、PIC16F18326の説明は、こちらのサイトに説明があり、参考になりました。

 I2Cを利用するために、MSSP1モジュールを導入します。

割込みを使いますので、Interruptモジュールの設定をします。

 Pin moduleで一応ウィークプルアップにチェックを入れます。
 I2CのSDA1は、9番ピンにSCL1は、10番ピンに割り当てられます。
 ここで、今までとの違いにもう一つ気が付きました。
 WPU enableの設定がありません。これまでですと、WPUにチェックを入れるとWPUEにチェックを入れろという注意がされたのですが、ありません。

 回路図です。


 これでいいのかな・・・・と思いつつ、プログラミングに進みます。
 プログラムです。
  printf()関数を使っていますので、projectのpropertiesで、XC8 Global OptionsのC standerdをC90にしてコンパイルします。
--------------------------------------------------------------------------
/*
* PIC16F18326 MCC AQM0802A test
* 2021.09.20
* JH7UBC Keiji Hata
*/

#include "mcc_generated_files/mcc.h"
#include "mcc_generated_files/examples/i2c1_master_example.h"

#define I2CLCD_AQM0802A 0x3e

//-------- send character ------------------------
void LCD_dat(char chr)
{
I2C1_Write1ByteRegister(I2CLCD_AQM0802A, 0x40, chr);
__delay_us(30); // 30us
}

//-------- send command -------------------------
void LCD_cmd(char cmd)
{
I2C1_Write1ByteRegister(I2CLCD_AQM0802A, 0x00, cmd);
if(cmd & 0xFC) // bit6 = 1
__delay_us(30); // 30us
else
__delay_ms(2); // 2ms Clear or Home
}

//-------- clear LCD--------------------------
void LCD_clr(void){
LCD_cmd(0x01);
}

//--------- Home -----------------------------
void LCD_home(void){
LCD_cmd(0x02);
}

//--------- Cursor X,Y -----------------------
void LCD_cursor(unsigned char x,unsigned char y){
if (y == 0)
LCD_cmd(0x80 + x);
if (y == 1)
LCD_cmd(0xc0 + x);
}

//-------- write 1 character to LCD ----------------
void putch(unsigned char ch){
LCD_dat(ch);
}

//-------- LCD initialize ---------------------------
void LCD_init(){
__delay_ms(40); //40ms wait
LCD_cmd(0x38); //8bit,2line
LCD_cmd(0x39); //IS=1 : extention mode set
LCD_cmd(0x14); //Internal OSC Frequency
LCD_cmd(0x70); //Contrast set
LCD_cmd(0x56); //Power/ICON/Contrast Control
LCD_cmd(0x6C); //Follower control
__delay_ms(200);//200ms wait
LCD_cmd(0x38); //IS=0 : extention mode cancel
LCD_cmd(0x0C); //Display ON
LCD_cmd(0x01); //Clear Display
__delay_ms(2); //wait more than 1.08ms
}

void main(void){
// initialize the device
SYSTEM_Initialize();

// Enable the Global Interrupts
INTERRUPT_GlobalInterruptEnable();

// Enable the Peripheral Interrupts
INTERRUPT_PeripheralInterruptEnable();

LCD_init();

printf("Hello!");

unsigned char count = 0;

while (1){
LCD_cursor(2,1);
printf("%3d",count);
count++;
__delay_ms(1000);
}
}

--------------------------------------------------------------------------
ブレッドボードです。

 無事、表示されました。

PIC16F1827 MCC RTC(DS1307)時計の試作

2021-08-10 11:26:58 | MPLAB X MCC
 東京オリンピックが終わり、しばらく放っておいたPIC16F1827 RTC 時計のプログラミングを再開しました。

 一応動きましたので、公開します。(まだバグがあるかも知れません)

 まず、回路図です。SETボタンを長押しすると時計セットモードになります。年、月、日、曜、時、分、秒の数値の変更は、UP/DOWNボタンで行います。SETモードでは、SETボタンを押すごとに年から秒まで変更できます。
 以前に試作したArduino Nano RTC(DS1307) 時計と基本的な操作、プログラムのアルゴリズムは同じです。


 MCCの設定です。まず、System moduleです。
 内部クロック、FOSC=16MHzとしました。
 ICSPを利用しますので、RA5は、RESET/MCLR/VPPとします。



 SETボタン=RB2
 UPボタン=RB3
 DOWNボタン=RB5
 として、inputとし、ウィークプルアップします。


 プログラムです。
-----------------------------------------------------------------------------------------------------
/*
* PIC12F1827 MCC RTC TEST
* 2021.08.10
* JH7UBC Keiji Hata
*/

#include "mcc_generated_files/mcc.h"
#include "mcc_generated_files/examples/i2c1_master_example.h"

//LCD関係定義
#define I2C_LCD_addr 0x27
#define LCD_EN 0b00000100//Enable
#define LCD_BL 0b00001000//Back Light
#define LCD_CMD 0x00
#define LCD_CHR 0x01
#define LCD_LINE1 0x80
#define LCD_LINE2 0xC0

//RTC関係定義
#define RTC_addr 0x68

char *week[] = {" ","MON","TUE","WED","THU","FRI","SAT","SUN"};
uint8_t REG[8] = {0x00,0x00,0x00,0x01,0x01,0x01,0x20,0x10};//時刻データ初期値2020/01/01 MON 00:00:00
int OLD_REG[7] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};//前の時刻データを保存するレジスタ
int Disp_REG[7];//表示用レジスタ
uint8_t REG_addr = 0x00;

//時計セット関係
#define SET RB2
#define UP RB3
#define DOWN RB5
int Num = 6; //Clock data number 6:year 5:month 4:day 3:week 2:hour 1:mminute 0:second
int count = 0;

//割込み関係
volatile int IntFlag = 0;

//I2C LCDに1byteのdataを書き込む
void I2C_write_data(uint8_t data){
I2C1_Write1ByteRegister(I2C_LCD_addr, (data | LCD_EN | LCD_BL),(data | LCD_BL));
__delay_us(100);
}

//I2C LCDにコマンドまたは文字を送る
void LCD_write(uint8_t data, uint8_t mode){
//上位4bitを送る
I2C_write_data((data & 0xF0) | mode);
//下位4bitを送る
I2C_write_data(((data << 4) & 0xF0) | mode);
}

//I2C LCD 初期化
void LCD_init(){
__delay_ms(40);
LCD_write(0x33,LCD_CMD);//8bit mode set 2回
LCD_write(0x32,LCD_CMD);//8bit mode set 1回,4bit mode set
LCD_write(0x06,LCD_CMD);//Entry mode set
LCD_write(0x0C,LCD_CMD);//display ON,cursol OFF,blink OFF
LCD_write(0x28,LCD_CMD);//Function set 4bit mode,2line
LCD_write(0x01,LCD_CMD);//Clear display
__delay_ms(1);
}

void LCD_home(){
LCD_write(0x02,LCD_CMD);
__delay_ms(1);
}

void LCD_cursor(uint8_t x,uint8_t y){
if(y == 0){
LCD_write(LCD_LINE1 + x,LCD_CMD);
}
if(y == 1){
LCD_write(LCD_LINE2 + x,LCD_CMD);
}
}

//1文字表示
void putch(char ch){
LCD_write(ch,LCD_CHR);
}

//時刻データをRTCに書き込む
void Time_data_write(){
for(uint8_t i=0;i<8;i++){
I2C1_Write1ByteRegister(RTC_addr,i,REG[i]);
}
}

//RTCから時刻データを読みだし、REG[]に格納
void Time_data_read(){
I2C1_WriteNBytes(RTC_addr,&REG_addr,1);
I2C1_ReadNBytes(RTC_addr,&REG,7);
}

//REG[]のデータ(HEX)をDisp_REG[]のデータ(10進)に変換
void HEX2DEC(){
for(uint8_t i=0;i<=7;i++){
Disp_REG[i] = ((REG[i] & 0xF0)>>4)*10 + (REG[i] & 0x0F);
}
}

//Disp_REG[]のデータ(10進)をREG[]のデータ(HEX)に変換
void DEC2HEX(){
for(uint8_t i=0;i<=7;i++){
REG[i] = ((Disp_REG[i] / 10) << 4) | (Disp_REG[i] % 10);
}
}

void LCD_print(uint8_t n){
printf("%02d",Disp_REG[n]);
OLD_REG[n]=Disp_REG[n];
}

//Timeデータの表示
void Time_disp(){
if(Disp_REG[6] != OLD_REG[6]){
LCD_cursor(2,0);
LCD_print(6);
}
if(Disp_REG[5] != OLD_REG[5]){
LCD_cursor(5,0);
LCD_print(5);
}
if(Disp_REG[4] != OLD_REG[4]){
LCD_cursor(8,0);
LCD_print(4);
}
if(Disp_REG[3] != OLD_REG[3]){
LCD_cursor(12,0);
printf(week[Disp_REG[3]]);
OLD_REG[3] = Disp_REG[3];
}
if(Disp_REG[2] != OLD_REG[2]){
LCD_cursor(4,1);
LCD_print(2);
}
if(Disp_REG[1] != OLD_REG[1]){
LCD_cursor(7,1);
LCD_print(1);
}
if(Disp_REG[0] != OLD_REG[0]){
LCD_cursor(10,1);
LCD_print(0);
}
}

void Time_UP_DOWN(uint8_t n){
if(UP == 0){
Disp_REG[n]++;
while(UP == 0){
__delay_ms(10);
}
}
if(DOWN == 0){
Disp_REG[n]--;
while(DOWN == 0){
__delay_ms(10);
}
}
}

void Year_set(){
LCD_cursor(0,1);
printf("Y");
while(SET == 1){
Time_UP_DOWN(6);
if(Disp_REG[6]>=100){
Disp_REG[6]=99;
}
if(Disp_REG[6]<0){
Disp_REG[6]=0;
}
Time_disp();
__delay_ms(10);
}
while(SET == 0){
}
OLD_REG[6] = Disp_REG[6];
Num--;
}

void Month_set(){
LCD_cursor(0,1);
printf("M");
while(SET == 1){
Time_UP_DOWN(5);
if(Disp_REG[5]>12){
Disp_REG[5]=1;
}
if(Disp_REG[5]<1){
Disp_REG[5]=12;
}
Time_disp();
__delay_ms(10);
}
while(SET == 0){
}
OLD_REG[5] = Disp_REG[5];
Num--;
}

void Day_set(){
LCD_cursor(0,1);
printf("D");
while(SET == 1){
Time_UP_DOWN(4);
if(Disp_REG[4]>31){
Disp_REG[4]=1;
}
if(Disp_REG[4]<1){
Disp_REG[4]=31;
}
Time_disp();
__delay_ms(10);
}
while(SET == 0){
}
OLD_REG[4] = Disp_REG[4];
Num--;
}

void Week_set(){
LCD_cursor(0,1);
printf("W");
while(SET == 1){
Time_UP_DOWN(3);
if(Disp_REG[3]>7){
Disp_REG[3]=1;
}
if(Disp_REG[3]<1){
Disp_REG[3]=7;
}
Time_disp();
__delay_ms(10);
}
while(SET == 0){
}
OLD_REG[3] = Disp_REG[3];
Num--;
}

void Hour_set(){
LCD_cursor(0,1);
printf("h");
while(SET == 1){
Time_UP_DOWN(2);
if(Disp_REG[2]>23){
Disp_REG[2]=0;
}
if(Disp_REG[2]<0){
Disp_REG[2]=23;
}
Time_disp();
__delay_ms(10);
}
while(SET == 0){
}
OLD_REG[2] = Disp_REG[2];
Num--;
}

void Minute_set(){
LCD_cursor(0,1);
printf("m");
while(SET == 1){
Time_UP_DOWN(1);
if(Disp_REG[1]>59){
Disp_REG[1]=0;
}
if(Disp_REG[1]<0){
Disp_REG[1]=59;
}
Time_disp();
__delay_ms(10);
}
while(SET == 0){
}
OLD_REG[1] = Disp_REG[1];
Num--;
}

void Second_set(){
LCD_cursor(0,1);
printf("s");
while(SET == 1){
Time_UP_DOWN(0);
if(Disp_REG[0]>59){
Disp_REG[0]=0;
}
if(Disp_REG[0]<0){
Disp_REG[0]=59;
}
Time_disp();
__delay_ms(10);
}
while(SET == 0){
}
OLD_REG[0] = Disp_REG[0];
Num--;
}

void Time_set(){
while(Num > -1){
switch(Num){
case 6:
Year_set();
break;
case 5:
Month_set();
break;
case 4:
Day_set();
break;
case 3:
Week_set();
break;
case 2:
Hour_set();
break;
case 1:
Minute_set();
break;
case 0:
Second_set();
break;
}
}
LCD_cursor(0,1);
printf(" ");
DEC2HEX();//Disp_REGデータ(10進)をREGデータ(HEX)に変換する
Time_data_write();//変更されたデータをRTCに書き込む
}

void main(){
// initialize the device
SYSTEM_Initialize();
// Enable the Global Interrupts
INTERRUPT_GlobalInterruptEnable();
// Enable the Peripheral Interrupts
INTERRUPT_PeripheralInterruptEnable();

LCD_init();

Time_data_write();//時刻をセット

//固定文字を表示
LCD_home();
printf("20 / / ( )");
LCD_cursor(6,1);
printf(": :");

//時刻表示
HEX2DEC();
Time_disp();

while (1){
if(IntFlag == 1){ //RB0にIOC割込みがあったら
Time_data_read();//RTCから時刻を読み出し
HEX2DEC(); //HEX→10進変換
Time_disp(); //時刻を表示する
IntFlag = 0; //割込みフラッグを降ろす
}

count = 0;
if(SET == 0){
while(SET == 0){
count++;
__delay_ms(5);
}
}
if(count>100){ //SETボタンが長押しされたら
INTCONbits.IOCIE = 0;//IOC割込み停止
INTCONbits.IOCIF = 0;//IOC割込みフラッグクリア
IntFlag = 0;
Time_set(); //時刻セットルーチンへ
Num = 6;
INTCONbits.IOCIE = 1;//IOC割込み再開
}
__delay_ms(10);
}
}

-----------------------------------------------------------------------------------------------------
ブレッドボードです。