PICでI2Cを試す(PIC16F1938実装編)

ピン数の多いPIC16F1938を使ってI2Cのデータを表示するデバイスを作った。
次の回路図では7セグLEDのための抵抗に表示の関係で2kΩと書いてあるけど、実際には2.2kΩを使っている。しかし、これらは1kΩ以下くらいにすれば良かったと思っている。
7セグLEDは半透明なカバーが付いているし、特に桁が2桁あってダイナミック点灯にしているから暗くなりがちなので。

PIC16F1938のI2Cデバッグデバイスの回路図

PIC16F1938のI2Cデバッグデバイスの回路図

PIC16F1938 I2Cデバッグデバイス

PIC16F1938 I2Cデバッグデバイス

送信するバイト数を変えられるようにArduinoのスケッチを書き換えた。

#include <Wire.h>

void setup() {
  // put your setup code here, to run once:
  Wire.begin();
  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
  if (Serial.available()) {
    delay(100);
    Wire.beginTransmission(0x20);
    while (Serial.available() > 0) {
      Wire.write(Serial.read());
    }
    Wire.endTransmission();
  }
}

PICのソースコード。

/* 
 * File:   main.c
 * Author: sakai
 *
 * Created on 2015/05/05, 6:58
 */

#include <stdio.h>
#include <stdlib.h>
#include <xc.h>

#define _XTAL_FREQ  32000000

#pragma config FOSC = INTOSC  // INTOSCIO
#pragma config CLKOUTEN = OFF
#pragma config FCMEN = OFF
#pragma config IESO = OFF
#pragma config MCLRE = ON
#pragma config BOREN = ON   // Brown Out Detect
#pragma config WDTE = OFF
#pragma config CPD = OFF    // Data Code Protection bit
#pragma config CP = OFF
#pragma config PWRTE = ON
#pragma config PLLEN = OFF
#pragma config STVREN = ON
#pragma config WRT = OFF
#pragma config BORV = HI
#pragma config LVP = OFF

#define MAX_BUFF    (32)

unsigned char flag = 0;
unsigned char data[MAX_BUFF];
unsigned char data_flag = 0;
unsigned char dp_flag = 0;
unsigned char loop = 0;

static void interrupt intr(void) {
    // 割り込み
    if (SSPIF == 1) {
        data[data_flag] = SSPSTAT;
        data_flag++;
        if (SSPSTAT & 0b00000001) {
            data[data_flag] = SSPBUF;
            data_flag++;
        }
        SSPCON1 = 0b11111110;
        SSPIF = 0; // クリア
        loop = 0;
    }
}

void display_digit(unsigned char b, int col) {
    PORTB = 0b00000000;
    unsigned char data_a;
    switch (b) {
        case 0:
            data_a = 0b00111111;
            break;
        case 1:
            data_a = 0b00100100;
            break;
        case 2:
            data_a = 0b01110011;
            break;
        case 3:
            data_a = 0b01110110;
            break;
        case 4:
            data_a = 0b01101100;
            break;
        case 5:
            data_a = 0b01011110;
            break;
        case 6:
            data_a = 0b01011111;
            break;
        case 7:
            data_a = 0b00110100;
            break;
        case 8:
            data_a = 0b01111111;
            break;
        case 9:
            data_a = 0b01111110;
            break;
        case 0x0a:
            data_a = 0b01111101;
            break;
        case 0x0b:
            data_a = 0b01001111;
            break;
        case 0x0c:
            data_a = 0b00011011;
            break;
        case 0x0d:
            data_a = 0b01100111;
            break;
        case 0x0e:
            data_a = 0b01011011;
            break;
        case 0x0f:
            data_a = 0b01011001;
            break;
        default:
            data_a = 0b00000000;
            break;
    }
    if (dp_flag & 1) {
        if (col == 1) {
            data_a |= 0b10000000;
        }
    } else if (dp_flag & 2) {
        if (col == 2) {
            data_a |= 0b10000000;
        }
    }
    PORTA = data_a;
    unsigned char data_b;
    if (col == 1) {
        data_b = 0b00000010;
    } else {
        data_b = 0b00000100;
    }
    if (dp_flag) {
        data_b |= 1;
    }
    PORTB = data_b;
}
/*
 * 
 */
int main(int argc, char** argv) {
    OSCCON = 0b11110000;
    // A, Bポートの設定
    ANSELA = 0;
    ANSELB = 0;
    TRISA = 0b00000000;
    TRISB = 0b00000000;
    PORTA = 0b00000000;
    PORTB = 0b00000000;
    // I2Cスレーブモードの設定
    SSPADD = 0x40; // アドレス=0x20
    SSPCON1 = 0b11111110;  // Slave 7bit address
    SSPCON2 = 0b10000001;  // SEN:1 clock stretch enable -> CKP:0
    SSPSTAT = 0b00000000;
    // 割り込み可能に設定
    PIE1     = 0b00001000;
    INTCON   = 0b11000000;

    unsigned char index = 0;
    unsigned char clear_count = 0;

    while (1) {
        if (data_flag) {
            if (index == 0) {
                display_digit(data_flag>>4, 1);
                __delay_ms(2);
                display_digit(data_flag&0x0f, 2);
                __delay_ms(2);
            } else {
                unsigned char disp = data[index - 1];
                display_digit(disp>>4, 1);
                __delay_ms(2);
                display_digit(disp&0x0f, 2);
                __delay_ms(2);
            }
        } else {
            display_digit(0x20, 1);
            __delay_ms(2);
            display_digit(0x20, 2);
            __delay_ms(2);
        }
        loop++;
        if (loop >= 150) {
            if (dp_flag == 0) {
                dp_flag = 2;
            } else {
                dp_flag = 0;
            }
            loop = 0;
            index++;
            if (index > data_flag) {
                index = 0;
                clear_count++;
                if (clear_count > 5) {
                    clear_count = 0;
                    data_flag = 0;
                }
            }
        }
    }
    
    return (EXIT_SUCCESS);
}
カテゴリー: Arduino, PIC, 作ったモノ, 回路 タグ: , パーマリンク

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA