/*****************************(abc933-18326.c)*******
* 簡易CANコンバーター *
****************************************************/
#include "myProject.h"
#include "myFunction.h"
#include "mcp_can_dfs.h"
#include "skMCP25xx.h"
#include "i2c_SSD1306.h"
#define USE_ASC_FONT
#ifdef USE_ASC_FONT
#include "Font_8x16ASC.h"
#else
#include "Font_8x16NA.h"
#endif
#define USE_RA3_PORT
#ifdef USE_RA3_PORT
#define GET_SW() RA3_GetValue()
#else
#define GET_SW() SW0_GetValue()
#endif
#define MBF_SIZE 64 // メッセージBFサイズ
#define OLED_SZ 21 // OLED行表示最大文字数
char *Md_Msg[] = { "** Integer Mode",
"** Ascii Mode",
"** HexNum Mode",
"** Format Mode"
};
/************************************************************
* グローバル変数
*==========================================================*/
//--- タイマー用変数
uint8_t TFlg; // タイマーフラグ
//---- EUSARTシリアル用
char RBuf[EU_BFSIZE]; // BFSIZEはmyProject.hで宣言
uint8_t SFlg; // シリアル受信フラグ
//---- 汎用データ処理用
char Msg[MBF_SIZE]; // コメント等用文字列
char Dlm[] = ","; // 文字列区切りデリミタ
//---- OLED表示用
uint8_t CrtLn = 0; // OLED表示現在行
uint8_t DspMd = 0; // データ表示モード
uint8_t Mx_Ln = 4; // 最終行は5行目
//---- CAN用共通変数
uint32_t Crv_id = 0x123; // 受信id
uint8_t Crv_Flg = 0 ; // CAN受信有無フラグ
uint8_t Crv_len = 0 ; // CAN受信データサイズ
uint8_t Crv_Buf[8]; // CAN受信データ
char Crv_Fmt[9] = "SSSSSSSS"; // CAN受信書式データ
uint32_t Csd_id = 0x149; // 送信id
uint8_t Csd_len = 0 ; // CAN送信データサイズ
uint8_t Csd_Buf[8]; // CAN送信データ
char Csd_Fmt[9] = "SSSSSSSS"; // CAN送信書式データ
/*==================================================*
* 割り込みの処理 *
*--------------------------------------------------*/
//--- タイマ0 Callback関数 (1秒周期割り込み)
void TMR0_Process(void){
TFlg = 1; // タイマーフラグセット
}
//---- MCP2515のINTピン割り込み
void IOCCF2_Process(void) {
Crv_Flg = 1; // CAN受信(有り)セット
}
/*==================================================*
* OLED表示用関数 & 表示テスト関数 *
*--------------------------------------------------*/
//---- スクロール付き表示(5x7ドット文字)
// (スクロール範囲は[0 - Mx_Ln])
void i2cOLED_Prt(char *str) {
i2cOLED_posPX(CrtLn, 0);
i2cOLED_str(str);
if (CrtLn < Mx_Ln) CrtLn++;
else CrtLn = 0;
i2cOLED_Clr(CrtLn, CrtLn, 0);
}
//---- 半角文字表示
uint8_t i2cPrint_Hchr(uint8_t py, uint8_t x,char ch){
#ifdef USE_ASC_FONT
if((0x20 <= ch)&(ch <= 0x7F)){
x = i2cOLED_Ptn(py,x,2,8,(char *)F_asc[ch-0x20]);
#else
if((0x30 <= ch)&(ch <= 0x3A)){
x = i2cOLED_Ptn(py,x,2,8,(char *)F_hn[ch-0x30]);
}else if((0x41 <= ch)&(ch <= 0x5A)){
x = i2cOLED_Ptn(py,x,2,8,(char *)F_af[ch-0x41]);
}else if(ch == 0x20){
x = i2cOLED_Ptn(py,x,2,8,(char *)F_sp);
}else if((0x2A <= ch)&(ch <= 0x2F)){
x = i2cOLED_Ptn(py,x,2,8,(char *)F_op[ch-0x2A]);
}else if((0x61 <= ch)&(ch <= 0x7A)){
x = i2cOLED_Ptn(py,x,2,8,(char *)F_af[ch-0x61]);
#endif
}else{
x = i2cOLED_Ptn(py,x,2,8,(char *)F_dt);
}
return x;
}
//---- 半角文字列の表示
uint8_t i2cPrint_Hstr(uint8_t py, uint8_t x, char *str) {
uint8_t n;
while(*str){
x = i2cPrint_Hchr(py,x,*str++);
}
return x;
}
//---- 配列データを16進数文字列に
void set_hex_data(char *bf, uint8_t *ary, uint8_t n){
uint8_t i;
for(i = 0; i < n; i++){
my_xtoa(bf, ary[i], 2);
bf += 2;
}
*bf = 0;
}
//--- 印刷可能な文字に変換して文字列を連結
void cv_prtcat(char *bf, char *str, uint8_t n){
uint8_t i;
for(i = 0; i < n; i++){
if(isprint(*str)) *bf++ = *str;
else *bf++ = 0x7F;
str++;
}
*bf = 0;
}
//---- OLEDとEUに文字列を出力
void OLED_EU_Prt(char *str){
i2cOLED_Prt(str);
EU_Puts(str);
}
//---- OLEDの最下行に半角文字表示
void OLED_Low_Hprt(char *str){
i2cOLED_Clr(6, 7, 0);
i2cPrint_Hstr(6, 0, str); // 半角文字表示
}
//---- 表示モードの変更
void chg_dspMd(uint8_t md) {
if(md > 3) md = 0;
i2cOLED_Clr(0, 7, 0); CrtLn = 0;
if(md < 2) Mx_Ln = 4;
else Mx_Ln = 7;
OLED_EU_Prt(Md_Msg[md]);
DspMd = md;
}
/************************************************************
* 送受信IDを設定
* char *str: 設定用文字列データ
* uint8_t sr: IDの種類(0:送信、1:受信)
*----------------------------------------------------------*/
void set_NewID(char *str, uint8_t sr){
uint32_t id;
id = my_xtol(str); // id取得
if(id){
id &= 0x3FF; // 11ビットに
if(sr){
Crv_id = id; // 受信idに設定
sprintf(Msg,"Snd_ID = %3X",Crv_id);
}else{
Csd_id = id; // 送信idに設定
sprintf(Msg,"Rsv_ID = %3X",Csd_id);
}
EU_Puts(Msg);
}
}
/************************************************************
* CAN書式データを格納
* char *fmt: 格納する書式文字列(Crv_Fmt[]/Csd_Fmt[])
* char *str: 書式指定文字列(コンマ区切り)
*----------------------------------------------------------*/
void set_CAN_Fmt(char *fmt, char *str){
char *ps; // 切出し文字列ポインタ
uint8_t p = 0; // 書式参照位置
char fch; // 書式指定文字
uint8_t i,j,k,n;
ps = strtok(str,Dlm); // 文字列の切り出し
do{
if(ps==NULL) break; // 文字列がなくなれば
fch = (char)toupper(*ps); // 大文字に
if(strlen(ps) > 1){ // パラメータがあれば
j = (uint8_t)atoi(ps+1); // 繰り返し数
}else{ // パラメータ無し
if(fch == 'S') j = 0; // Sでパラ無しは可変長
else j = 1;
}
switch(fch){
case 'S': k = j; break;
case 'U': case 'W': k = 2; break;
case 'L': k = 4; break;
default: k = 1; break;
}
if(j) n = j * k; // パラなし文字列以外の場合
else n = 8 - p; // パラなし文字列の場合
if((p + n) > 8) break; // 指定文字数オーバー
for(i = 0; i < n; i++){
fmt[p++] = fch; // 書式文字を指定数セット
}
ps = strtok(NULL,Dlm);
}while(p < 8); // 書式文字数が8文字以内なら
fmt[p] = 0; // 文字列終了
EU_Puts(fmt); // 変換結果表示
}
/*************************************************
* CAN受信処理
*================================================
* バイナリー配列を指定書式で文字列に追加
*---------------------------------------------*/
//--- 1バイトバイナリー => 数値文字列(最大3文字)
uint8_t set_B_S(char *str, uint8_t *d){
char s[10];
sprintf(s,"%d", d);
strcat(str,s);
return (uint8_t)strlen(s);
}
//--- 2バイトバイナリー => 数値文字列(最大5文字)
uint8_t set_U_S(char *str, uint8_t *bf){
union {
uint8_t b[2];
uint16_t u; } data;
char s[10];
data.b[0] = *bf++;
data.b[1] = *bf;
sprintf(s,"%d",data.u);
strcat(str,s);
return (uint8_t)strlen(s);
}
//--- 1バイトバイナリー => 16進数文字列(2文字)
uint8_t set_H_S(char *str, uint8_t *h){
union {
uint8_t b[2];
uint16_t w; } data;
data.b[0] = *h;
my_xtoa((char *)str,data.w,2);
return 2;
}
//--- 2バイトバイナリー => 16進数文字列(4文字)
uint8_t set_W_S(char *str, uint8_t *bf, uint8_t en){
union {
uint8_t b[2];
uint16_t w; } data;
uint8_t i;
for(i = 0; i < 2; i++)
data.b[i]= *bf++;
if(en) data.w = exchg_word(data.w);
my_xtoa((char *)str,data.w,4);
return 4;
}
//--- 4バイトバイナリー => 16進数文字列(6文字)
uint8_t set_L_S(char *str,uint8_t *bf, uint8_t en){
union {
uint8_t b[4];
uint32_t L; } data;
uint16_t h;
uint8_t i;
for(i = 0; i < 4; i++)
data.b[i]= *bf++;
if(en) data.L = exchg_long(data.L);
my_xLtoa2((char *)str,data.L,8);
return 8;
}
/*===========================================================
* 書式指定に従い、文字列データを変換し、バッファーに追加
* char *str: 変換データを格納する文字列
* uint8_t *bf: 変換する元データ配列
* uint8_t of: 書式、データ参照オフセット位置
* return -> 正常に変換(格納)できた文字数
*----------------------------------------------------------*/
uint8_t set_RecvData(char *str, uint8_t *rbf, uint8_t of){
char fch; // 書式指定文字
uint8_t n = 0; // 格納した変換文字数
uint8_t rm; // 参照残りバイト
uint8_t i;
fch = Crv_Fmt[of];
rm = 8 - of;
switch(fch){ // 書式文字が・・
case 'S': // 文字列の場合
for(i = 0; i < rm; i++){
if(Crv_Fmt[of+i] == 'S'){ // 書式指定が'S'なら
*str++ = (char)*rbf++; // 文字をコピー
}else{
break; // 'S'でなければ変換終了
}
}
n = i; // 書き込んだ文字数
break;
case 'C': // 文字を1バイトに
if(isprint(*rbf)) *str = *rbf;
else *str = '*'; //0x7F;
n = 1;
break;
case 'B': // 数値文字列(1-3)に
n = set_B_S(str, *rbf);
break;
case 'H': // 16進文字列(2)に
n = set_H_S(str, rbf);
break;
case 'U': // 数値文字列(1-5)に
n = set_U_S(str, rbf);
break;
case 'W': // 16進文字列(-4)に
n = set_W_S(str, rbf, 1);
break;
case 'L': // 16進文字列(-6)に
n = set_L_S(str, rbf, 1);
break;
}
return n;
}
/*==========================================================
* データを指定書式でデータを文字列に格納
* [ 参照する書式データは、Crv_Fmt() ]
* char *str: 変換後に格納する文字列
* uint8_t *rbf: 変換する配列データ
* uint8_t sz: 受信したデータ数
* return -> 正常に変換(格納)できた文字数(失敗時は0)
*---------------------------------------------------------*/
uint8_t set_RdatF(char *str, uint8_t *rbf, uint8_t sz){
uint8_t n = 0; // 追加文字数カウンタ
uint8_t of = 0; // 書式参照オフセット
char fch; // 書式指定文字
char ss[20];
do{
fch = Crv_Fmt[of]; // 対応データ位置の書式
if(fch){
if(of>0){
*str = ','; // 文字区切り追加
str++;
}
n = set_RecvData(str,rbf,of);
if(n){ // 変換データが有効
switch(fch){ // 参照、変換位置移動
case 'S':
of += n; rbf += n;
break;
case 'C': case 'B': case 'H':
of += 1; rbf += 1;
break;
case 'U': case 'W':
of += 2; rbf += 2;
break;
case 'L':
of += 4; rbf += 4;
break;
}
str += n; // 次格納位置へ移動
}else{ // 変換データが無効
break; // ループ脱出
}
}else{ // 書式データ無し
break; // ループ脱出
}
if(of >= sz) break;
}while(of < 8); // 有効データが7文字以内
*str = 0;
return of; // 有効データ数を返す
}
/*===================================================*
* CAN受信の処理 *
*---------------------------------------------------*/
void CheckReceiveProcess(void) {
union {
unsigned char c[2];
unsigned int i;
} data;
unsigned long id;
// INTピン割り込みが有れば処理する
if (Crv_Flg) {
Crv_Flg = 0; // 割り込みフラグをクリア
while (CAN_MSGAVAIL == mcp_checkReceive()) {
// 受信したメッセージを読み込む,
mcp_readMsgBuf(&Crv_len, Crv_Buf);
id = mcp_getCanId();
my_xtoa(Msg, (uint16_t)id, 3); // id表示設定
Msg[3] = ':'; Msg[4] = ' ';
// データフレームなら
if (mcp_isRemoteRequest() == 0) {
// idが一致するか表示変換モードが3なら
if((id == Crv_id)|(DspMd == 3)){ // 書式指定表示
set_RdatF(Msg+5,Crv_Buf,Crv_len);
EU_Puts(Msg);
if(strlen(Msg)>OLED_SZ){
Msg[OLED_SZ-1] = 0;
}
i2cOLED_Prt(Msg);
}else{
switch(DspMd){
case 0: // 整数表示
data.c[0] = Crv_Buf[0];
data.c[1] = Crv_Buf[1];
my_utoa(Msg + 5, data.i);
OLED_EU_Prt(Msg);
OLED_Low_Hprt(Msg); // 半角文字表示
break;
case 1: // 文字列表示
cv_prtcat(Msg+5, (char *)Crv_Buf, Crv_len);
OLED_EU_Prt(Msg);
OLED_Low_Hprt(Msg); // 半角文字表示
break;
case 2: // 16進数表示
set_hex_data(Msg+5,Crv_Buf,Crv_len);
OLED_EU_Prt(Msg);
break;
}
}
}else{ // リモートフレーム
Msg[5] = 0;
strcat(Msg," -- Remote");
OLED_EU_Prt(Msg);
if(DspMd < 2){
OLED_Low_Hprt(Msg); // 半角文字表示
}
}
}
}
}
/*==========================================================
* 受信データ処理( '|'コマンド処理 )
* char *str: 受信指示文字列
* Return -> 受信データ数(n=0なら送信データ無し)
*---------------------------------------------------------*/
void CAN_Rcv_Cmd(char *str){
char *ps;
char cmd;
uint32_t id;
uint8_t n, m;
if(strlen(RBuf) == 1){ // '|'のみ
EU_Puts(Crv_Fmt); // 現在書式表示
return;
}
ps = ++str; // *psは次文字に
cmd = (char)toupper(*ps);
switch(cmd){
case 'X':
ps = strtok(ps+1,Dlm); // 文字列の切り出し
if(ps!=NULL){ // id指定があれば
set_NewID(ps,1); // 受信idをセット
}
break;
case 'M': // 表示モード変更
if(strlen(ps) < 2){ // "|M"の2文字なら
DspMd++;
chg_dspMd(DspMd);
}else{
m = (uint8_t)atoi(ps+1);
chg_dspMd(m);
}
break;
default:
set_CAN_Fmt(Crv_Fmt, ps); // 書式データを格納
break;
}
}
/************************************************************
* CAN送信の処理
*==========================================================*/
//---- CAN送信実施(標準id、送信済み待ち)
/* uint32_t id: 11ビット識別子
* uint8_t *buf: 送信するデータ列アドレス
* uint8_t len: 送信するバイト数(len=0ならリモート)
*---------------------------------------------------------*/
void CAN_Send(uint32_t id, uint8_t *buf, uint8_t len){
uint8_t res;
if(len == 0)
res = mcp_sendMsgBuf(id,CAN_STDID,CAN_RMTFRM,0,buf,1);
else
res = mcp_sendMsgBuf(id,CAN_STDID,CAN_DTFRM,len,buf,1);
}
//--- 最大8文字の文字列を(Csd_idで)CAN送信
void CAN_Snd_str(char *buf){
uint8_t n;
n = (uint8_t)strlen(buf);
if(n > 8) n = 8;
CAN_Send(Csd_id,(uint8_t *)buf,n);
}
/*==========================================================
* 文字列データを指定書式で変換しバイナリー配列に追加
*---------------------------------------------------------*/
//---- 数値文字列 -> 1バイトバイナリー
uint8_t set_S_B(uint8_t *bf, char *str){
*bf = (uint8_t)atoi(str);
return 1;
}
//---- 数値文字列 -> 2バイトバイナリー
uint8_t set_S_U(uint8_t *bf, char *str, uint8_t en){
union { char c[2] ;
uint16_t u ; } dt ;
dt.u = (uint16_t)atoi(str);
if(en) dt.u = exchg_word(dt.u); // 上下バイト入替
bf[0] = dt.c[0], bf[1] = dt.c[1];
return 2;
}
//---- 16進数文字列 -> 1バイトバイナリー
uint8_t set_S_H(uint8_t *bf, char *str){
*bf = (uint8_t)my_xtol(str);
return 1;
}
//---- 16進数文字列 -> 2バイトバイナリー
uint8_t set_S_W(uint8_t *bf, char *str, uint8_t en){
union { char c[2] ;
uint16_t w ; } dt ;
dt.w = (uint16_t)my_xtol(str);
if(en) dt.w = exchg_word(dt.w); // 上下バイト入替
bf[0] = dt.c[0], bf[1] = dt.c[1];
return 2;
}
//---- 16進数文字列 -> 4バイトバイナリー
uint8_t set_S_L(uint8_t *bf, char *str, uint8_t en){
union { char c[4] ;
uint32_t L ;
} dt ;
dt.L = my_xtol(str);
if(en) exchg_long(dt.L); // 上下バイト入替
bf[0] = dt.c[0], bf[1] = dt.c[1];
bf[2] = dt.c[2], bf[3] = dt.c[3];
return 4;
}
/*===========================================================
* 書式指定に従い、文字列データを変換し、バッファーに追加
* char fch: 書式指定文字
* uint8_t *bf: 格納データ配列(最大8byte)
* char *str: 変換する文字列
* uint8_t sz: 格納出来るデータサイズ
* return -> 正常に変換(格納)できた文字数
*----------------------------------------------------------*/
uint8_t set_SendData(char fch, uint8_t *bf, char *str, uint8_t sz){
uint8_t n,i,p;
p = 8 - sz;
switch(fch){
case 'S': // 文字列
n = (uint8_t)strlen(str);
if(n > sz) n = sz;
for(i = 0; i < n; i++){ // 最大n文字
if(Csd_Fmt[p+i]=='S'){ // 書式指定が'S'なら
*bf++ = (uint8_t)*str++; // 文字をコピー
}else{
break; // 'S'でなければ中断
}
}
n = i; // 書き込んだ文字数
break;
case 'C': // 文字を1バイトに
*bf = (uint8_t)*str; n = 1;
break;
case 'B': // 数値文字列を1バイトに
set_S_B(bf, str); n = 1;
break;
case 'H': // 16進文字列を1バイトに
set_S_H(bf, str); n = 1;
break;
case 'U': // 数値文字列を2バイトに
set_S_U(bf, str, 0); n = 2;
break;
case 'W': // 16進文字列を2バイトに
set_S_W(bf, str, 0); n = 2;
break;
case 'L': // 16進文字列を4バイトに
set_S_L(bf, str, 0); n = 4;
break;
}
return n;
}
/*==========================================================
* 文字列を切り出し、指定書式でデータを変換し配列に格納
* [ 参照する書式データは、Csd_Fmt() ]
* uint8_t *bf: 格納する配列データ
* char *str: 変換される文字列
* return -> 正常に変換(格納)できた文字数(失敗時は0)
*---------------------------------------------------------*/
uint8_t set_SdatF(char *bf, char *str){
char *ps; // 切出し文字列ポインタ
uint8_t n; // 変換・設定済バイト数
uint8_t p = 0; // 書式参照位置
char fch; // 書式指定文字
ps = strtok(str,Dlm); // 文字列の切り出し
do{
if(ps==NULL) break; // 文字列がなければ
fch = Csd_Fmt[p]; // 対応データ位置の書式
if(fch){
n = set_SendData(fch,Csd_Buf+p,ps,8-p);
if(n) p += n; // 変換データが有効
else break; // 変換データが無効
}
else{ // 書式データ無し
break;
}
ps = strtok(NULL,Dlm); // 次の文字列取得
}while(p < 8); // 有効データが7文字以内
return p; // 有効データ数を返す
}
/*==========================================================
* 送信データ処理( '~'コマンド処理 )
* char *str: 送信指示文字列
* Return -> 有効送信データ数(n=0なら送信データ無し)
*---------------------------------------------------------*/
void CAN_Snd_Cmd(char *str){
char *ps;
char cmd;
uint32_t id;
uint8_t n, m;
if(strlen(RBuf) == 1){ // '~'のみ
EU_Puts(Csd_Fmt); // 現在書式表示
return;
}
ps = ++str; // *psは次文字に
cmd = (char)toupper(*ps);
switch(cmd){
case 'X': case 'R':
ps = strtok(ps+1,Dlm); // 文字列の切り出し
if(ps!=NULL){ // id指定があれば
set_NewID(ps,0);
}
if( cmd == 'R') // リモート指示なら
CAN_Send(Csd_id,Csd_Buf,0); // リモートCAN送信
break;
case 'M': // 表示モード変更
if(strlen(ps) < 2){ // "|M"の2文字なら
DspMd++;
chg_dspMd(DspMd);
}else{
m = (uint8_t)atoi(ps+1);
chg_dspMd(m);
}
break;
default:
set_CAN_Fmt(Csd_Fmt, ps); // 書式データを格納
break;
}
}
/*==========================================================
* 有効なデータをCAN送信
* char *str: 送信したいデータ
* (データは指定書式に従い、変換されて送信される)
*---------------------------------------------------------*/
uint8_t CAN_SendData(char *str){
uint8_t sn = 0;
uint8_t i;
char *p;
sn = set_SdatF(Csd_Fmt, str); // 書式付きデータセット
if(sn){ // データが有効なら
CAN_Send(Csd_id,Csd_Buf,sn); // CAN送信実施
sprintf(Msg,"%3X : ",Csd_id);
p = Msg + 6;
for( i= 0; i < sn; i++){
my_xtoa(p,Csd_Buf[i],2);
p+=2;
}
*p = 0;
EU_Puts(Msg); // データは16進数文字列で
}
return sn;
}
/***********************************************************
* スイッチアクション
*---------------------------------------------------------*/
//---- RA3スイッチ・チェック・処理
void chk_RA3_Proc(void){
if(RA3_GetValue()==0){ // RA3_SWが押されていたら
__delay_ms(40); // チャッタリング対策
if(RA3_GetValue()==0){ // まだ押されていたら
chg_dspMd(++DspMd);
while(RA3_GetValue() == 0); // キーが離れるまで待つ
}
__delay_ms(100); // チャッタリング対策
}
}
//---- SW0(RA0)スイッチ・チェック・処理
void chk_SW0_Proc(void){
static uint8_t d[] = { '0',0 };
if(SW0_GetValue() == 0){ // SW0が押されていたら
__delay_ms(40); // チャッタリング対策
if(SW0_GetValue() == 0){ // まだ押されていたら
d[0] ^= 1; // ビット0を反転
CAN_Send(0x149,d,1); // データ1文字CAN送信
while(SW0_GetValue() == 0); // キーが離れるまで待つ
}
__delay_ms(100); // チャッタリング対策
}
}
/********************************************************
* Main application *
********************************************************/
void main(void) {
uint8_t cmd; // コマンド
uint8_t buf[8]; // CANデータ用
uint8_t sw; // スイッチ情報
char s[12];
SYSTEM_Initialize();
SSP1CON1bits.SSPEN = 1; //SPI1を有効に
TMR0_SetInterruptHandler(TMR0_Process); // Timer0 Callback関数
IOCCF2_SetInterruptHandler(IOCCF2_Process); // Pin割込CallBack
INTERRUPT_GlobalInterruptEnable();
INTERRUPT_PeripheralInterruptEnable();
i2cOLED_init();
i2cOLED_Clr(0, 7, 0);
LED_SetHigh();
// __delay_ms(1000); // CANモジュール準備待ち
EU_Puts("start");
// MCP25625によるCAN通信の初期化
// CANバス通信速度=100Kbps MCP25625のクロック=16MHz
while (CAN_OK != mcp_begin(CAN_100KBPS, MCP_16MHz)) {
OLED_EU_Prt("InitFail");
exit(1); // エラー終了
}
OLED_EU_Prt("Init OK!");
// MASK0->Filter0->RXB0(オーバフローでRXB1)のみ使用
mcp_init_Mask(0, 0, 0x3ff); // 全て受付る
mcp_init_Filt(0, 0, Crv_id); // 受信Allですが
// MCP_PXB_RX_ANYに設定するとフィルター基準は無視
OLED_EU_Prt("ready!");
while (1) {
if(TFlg){ // タイマー割込有り?
TFlg = 0;
LED_Toggle(); // LED点灯トグル
}
chk_RA3_Proc(); // RA3スイッチ処理
// chk_SW0_Proc(); // SW0(RA0)スイッチ処理
CheckReceiveProcess(); // CAN受信データ確認・処理
if (SFlg) { // シリアル入力があれば
cmd = RBuf[0];
switch (cmd) {
case '~': // 送信書式設定など
CAN_Snd_Cmd(RBuf);
break;
case '|': // 受信書式設定など
CAN_Rcv_Cmd(RBuf);
break;
case '^': // コマンドが'^'なら
if(strlen(RBuf)>0)
CAN_Snd_str(RBuf+1); // 文字列送信
break;
default:
CAN_SendData(RBuf); // 書式変換データをCAN送信
break;
}
SFlg = 0;
}
}
}
/*************** End of File **********************/
|