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

