/*****************************(abc929-18326.c)***********
* 簡易CANバスモニター(MCF2515モジュール) *
*********************************************************/
#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
// 共通変数の宣言
char RBuf[EU_BFSIZE]; // BFSIZEはmyProject.hで宣言
uint8_t SFlg = 0; // シリアル受信フラグ
uint8_t CrtLn = 0; // OLED表示現在行
uint8_t H_Chr = 0; // 整数表示モード
uint8_t Mx_Ln = 4; // 最終行は5行目
unsigned char flagRecv = 0; // CAN受信フラグ
unsigned char len = 0; // CAN受信文字数
unsigned char RcvBuf[8]; // CAN受信データ
/*==========================================================*
* MCP2515のINTピン割り込み処理 *
*----------------------------------------------------------*/
void IOCAF2_Process(void) {
flagRecv = 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);
}
//---- 8x16ドット半角文字表示
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;
}
//---- 半角文字の表示テスト
void test_HanK(void) {
uint8_t i, j;
for(j = 0; j < 4; j++){
for(i = 0; i < 16; i++){
i2cPrint_Hchr(j*2, i*8, 0x20+j*16+i);
// i2cPrint_Hchr(j*2, i*8, 0x40+j*16+i);
}
}
}
//---- 配列データを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); // 半角文字表示
}
//---- 表示モードの変更
uint8_t chg_dspMd(void) {
i2cOLED_Clr(0, 7, 0); CrtLn = 0;
switch (H_Chr) {
case 0: H_Chr = 1; Mx_Ln = 4;
#ifdef USE_ASC_FONT
OLED_EU_Prt("** Ascii Mode");
#else
OLED_EU_Prt("** N-Alfa Mode");
#endif
break;
case 1: H_Chr = 2; Mx_Ln = 7;
OLED_EU_Prt("** HexNum Mode");
break;
case 2: H_Chr = 0; Mx_Ln = 4;
OLED_EU_Prt("** Integer Mode");
break;
}
return H_Chr;
}
/*==========================================================*
* CAN受信の処理 *
*----------------------------------------------------------*/
void CheckReceiveProcess(void) {
union {
unsigned char c[2];
unsigned int i;
} data;
unsigned long id;
char buf[16];
// INTピン割り込みが有れば処理する
if (flagRecv) {
flagRecv = 0; // 割り込みフラグをクリア
while (CAN_MSGAVAIL == mcp_checkReceive()) {
// 受信したメッセージを読み込む,
mcp_readMsgBuf(&len, RcvBuf);
id = mcp_getCanId();
my_xtoa(buf, (uint16_t)id, 3);
buf[3] = ':'; buf[4] = ' ';
// データフレームなら
if (mcp_isRemoteRequest() == 0) {
if(H_Chr == 0){ // 整数表示
data.c[0] = RcvBuf[0];
data.c[1] = RcvBuf[1];
my_utoa(buf + 5, data.i);
OLED_EU_Prt(buf);
OLED_Low_Hprt(buf); // 半角文字表示
}else if(H_Chr == 1){ // アスキー表示
cv_prtcat(buf+5, (char *)RcvBuf, len);
OLED_EU_Prt(buf);
OLED_Low_Hprt(buf); // 半角文字表示
}else{ // 16進数表示
set_hex_data(buf+5,RcvBuf,len);
OLED_EU_Prt(buf);
}
}else{ // リモートフレーム
buf[5] = 0;
strcat(buf," -- Remote");
OLED_EU_Prt(buf);
if(H_Chr < 2){
OLED_Low_Hprt(buf); // 半角文字表示
}
}
}
}
}
/*==========================================================*
* CAN送信テスト *
*----------------------------------------------------------*/
void CAN_Send(char *str, uint8_t *bf) {
uint16_t id;
uint8_t n, *p;
n = (uint8_t)strlen(str) - 1;
if(n == 0){ // パラメータ無し
id = 0x123;
// リモートフレーム送信
mcp_sendMsgBuf(id, CAN_STDID, CAN_RMTFRM, 0, bf, 1);
}else{
if(n > 8) n = 8; // 最大8文字まで
p = (uint8_t *)(str + 1);
id = 0x124;
// データーフレーム送信
mcp_sendMsgBuf(id, CAN_STDID, CAN_DTFRM, n, p, 1);
}
}
/************************************************************
* Main application *
************************************************************/
void main(void) {
uint8_t cmd; // コマンド
uint8_t buf[8]; // CANデータ用
uint8_t sw; // スイッチ情報
SYSTEM_Initialize();
SSP1CON1bits.SSPEN = 1; //SPI1を有効に
IOCAF2_SetInterruptHandler(IOCAF2_Process);
INTERRUPT_GlobalInterruptEnable();
INTERRUPT_PeripheralInterruptEnable();
i2cOLED_init();
i2cOLED_Clr(0, 7, 0);
OLED_EU_Prt("ready!");
// MCP2515によるCAN通信の初期化
// CANバス通信速度=100Kbps MCP2515のクロック=8MHz
while (CAN_OK != mcp_begin(CAN_100KBPS, MCP_8MHz)) {
OLED_EU_Prt("InitFail");
while (1); // 終了
}
OLED_EU_Prt("Init OK!");
// MASK0->Filter0->RXB0(オーバフローでRXB1)のみ使用
mcp_init_Mask(0, 0, 0x3ff); // 全て受付る
mcp_init_Filt(0, 0, 0x124); // ID:0x124のみ受け取る
// RXM = MCP_PXB_RX_ANY に設定するとフィルター基準は無視
// MCP2515のINTピン割り込みの設定
IOCAN2 = 1; // RA2をIOCで設定(立下げエッジで割込み発生)
IOCAF2 = 0; // フラグをクリアする
IOCIF = 0; // 状態変化割込フラグをクリア
IOCIE = 1; // 状態変化割り込みを有効にする
while (1) {
if(GET_SW()==0){ // スイッチONか
__delay_ms(50); // チャタリング対策
if(GET_SW()==0){ // やはりスイッチON?
chg_dspMd();
while(GET_SW()); // スイッチがOFFまで待つ
__delay_ms(100); // チャタリング対策
}
}
// 受信しているメッセージデータを調べる
CheckReceiveProcess();
if (SFlg) { // シリアル入力があれば
cmd = RBuf[0];
switch (cmd) {
case 'C': i2cOLED_Clr(0, 7, 0);
CrtLn = 0; break;
case 'H': test_HanK(); break;
case 'R': CAN_Send(RBuf,buf); break;
case 'M': chg_dspMd(); break;
}
SFlg = 0;
}
}
}
/****************** End of File *****************************/
|