PWMが3つできたので、I2Cで色を指定できたら便利と思って、ピン変化割り込みでI2Cを実装しようとして頓挫した。
ArduinoのWireライブラリを使ってマスタを作って、GP4(SDA), GP5(SCL)の割り込みで処理しようと思ってアドレスを受け取ってACKを返すところまで書いてテストしてみたけど、スタートコンディションが検出できない。
割り込みでGP4, GP5の変化をLEDにつなぐとそれなりにチカチカっとする。
で、割り込み処理をどんどんシンプルにしていったら割り込みが数回連続して来るので他のことが全然できていないことがわかった。
確かにタイミング的にSDAとSCL両方の変化を取るとかなり短い時間で割り込みがかかるからこれじゃダメ。
クロック(SCL)側だけにするとしても、100kbpsで転送するモードとしても、Hi, Loで割り込みがかかると200kHzで0.2MHzとなって、8MHzで動かしても実質2MHzだから10命令くらいしか動かせない。10命令じゃちょっと無理じゃないかな。
と、ここでPIC12F683でやるのは断念。
それでも他の人はPICでI2Cやってるからどうやってるんだろう?
/*
* File: main.c
* Author: sakai
*
* pic12f683_ioc
*
* Created on 2014/08/01, 1:33
*/
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
typedef unsigned char byte;
#define _XTAL_FREQ (8000000)
#pragma config FOSC = INTOSCIO // INTOSCIO
#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
#define MY_ADDRESS (33)
volatile byte last_sda = 0; // GP4
volatile byte curr_sda = 0; // GP4
volatile byte last_scl = 0; // GP5
volatile byte curr_scl = 0; // GP5
enum {
I2CCOND_IDLE = 0,
I2CCOND_START,
I2CCOND_ADDRESS,
I2CCOND_END
};
volatile byte i2c_cond = I2CCOND_IDLE;
volatile byte i2c_data = 0;
volatile byte i2c_count = 0;
volatile byte prev_data = 0;
volatile byte curr_data;
volatile byte flag = 0;
static void interrupt intr_ioc(void)
{
if (GPIF == 1) {
curr_data = GPIO;
flag++;
GPIF = 0;
}
}
/*
*
*/
int main(int argc, char** argv)
{
// クロックの設定
OSCCON = 0x70; // 8MHz (4MHzにするには0x60を設定)
// 使わない機能を停止
CMCON0 = 0x07; // コンパレータを停止し、
ANSEL = 0x00; // アナログ入力を使わない(デジタルI/Oへ設定)
// GPIOの入出力設定
TRISIO = 0x30; // GP4(SCL), GP5(SDA)を入力に
GP0 = 1;
GP1 = 1;
GP2 = 1;
// 割り込みの設定
IOC = 0x30; // GP4とGP5を割り込み可能に
INTCON = 0xA8; // GIE, T0IE, GPIE
while (1) {
if (flag) {
if (flag > 3) { // 3回以上連続して割り込みがあった
GP2 = 0;
} else {
GP2 = 1;
}
flag = 0;
} else {
GP2 = 1;
}
}
return (EXIT_SUCCESS);
}