ソースリスト(エゾマツ)
エゾマツに使ったプログラム、参考までに晒しときます。
アセンブリでやった作りかけもあるけど、Cでやったやつが今のところ完成版になったのでおいときます。
デバイス(品種)の定義は、IDEの設定のほうでしてください。
Cでやったっていっても、高性能マクロアセンブラー程度にも使い切れないので…
マイコンの内部の設定周りビットごと操作したりレジスターごと操作したりいろいろ統一してないところもあるので
みにくいです。操作データも送信側と受信側で別々に加工してるし。
リストはMicrochip MPLAB IDEに只でくっついてくる、Hitec-Cでコンパイルしてやってください。
送信側のタイミングは部分的に最適化される、liteモードでうまくいくように設定しています。
後日プロジェクトをzipに固めたのと回路図も置きます。
行内コメントの修正など補足は、後日ここの記事を変更して行います。
リスト冒頭のinclude文の後の角括弧がきちんと表示されてなかったので、修正しました。また、本文とソースリストの区分けはっきりさせました。(2011/08/21)
PIC12F675用送信プログラム(次の行から)
#include <htc.h>
__CONFIG(FOSC_INTRCIO & WDTE_OFF & PWRTE_ON & MCLRE_OFF & BOREN_OFF & CP_OFF);
void adhenkan(unsigned char ch);
void trns_char(unsigned char data);void main(void)
{
unsigned char data = 0, chksum=0;
unsigned char d[3],i ;
//init periph
TRISIO=0b00000111; //GPIO0:2アナログ入力
ADCON0=0b00000000; //データは、左詰め(ADRESHに変換結果上位8ビットが保持される)
ANSEL=0b01010111; //Fosc/16,gpio0-2 are analog ins
CLRWDT();
GPIO = 0b00100000;while (1)
{
data = 0;chksum =170;
for (i=0;i<=2;i++) //input data { adhenkan(i); if (ADRESH < 0x80) d[i] = ADRESH ^ 0x7f; else d[i]= ADRESH; chksum += d[i]; } trns_char(170); for (i=0;i<=2;i++){ trns_char(d[i]);} trns_char(chksum); _delay(16800); //適当な周期になるよう調整 } } void adhenkan(unsigned char ch) { ADCON0 = 0b00000001 | (ch<<2); _delay(30); GO = 1; //変換スタート while(GO){} //終了待 return; } void trns_char(unsigned char data) //GPOIO5,88-90abt.9600bps@4MHz 104mis { //速度は、パソコン等で確認しやすいように、9600bpsや19200bpsくらいにする GPIO &= 0b00011111; //send start bit _delay(192); //88 for 9.6k for (char i = 0; i <= 7; i++) { if (data & 0b00000001) GPIO |= 0b00100000; else {GPIO &= 0b11011111; _delay(4); } data >>= 1;
_delay(182); //81 for 9.6k
}
GPIO |= 0b00100000; //send stop bit
_delay(194); //90 for 9.6k}
PIC16F648A用受信プログラム(次の行から)
#include <htc.h>
__CONFIG(FOSC_INTOSCIO & WDTE_OFF & PWRTE_ON & MCLRE_OFF & BOREN_OFF & LVP_OFF & CP_OFF);#define DELAY_LOOP1 _delay(200); //.1msec+程度待つ。データは、割り込みで受信される。
#define TIMEOUT_PRESET 40 //無通信タイムアウト:10msec程度にする。
//*上行の_delayの値に注意*_delay除いたループ実行時間約0.3msec@4MHz#define STEPFACTOR 96 //分解能(64:2段,96:4段,112:8段,120:16段,124:32段,126:64段,127:128段)
unsigned char ct=0,rsdata2[5], chksum=0, p=0, buffull=0;void interrupt isr_ser(void);
void main(void)
{
unsigned char c[3],i,rsdata[3], portdata=0, portdata2;//init periph
PCON=0b00001000;
CMCON=0b00000111;
TRISA=0;
TRISB=0b00000110;//init usart
SPBRG = 51; // 25 =9600bps@4MHz 51=4800@4M
TXSTA = 0b00000100; //async, 8bit, high
RCSTA = 0b10010000;CLRWDT();
INTCON=0;
PIE1=0;
RCIE = 1;
PEIE = 1;
GIE = 1;
PORTA=0;
PORTB=0;
rsdata[0] = 0;rsdata[1] = 0;rsdata[2] = 0;while (1)
{
if (buffull)
{
ct = TIMEOUT_PRESET;
buffull = 0;// check for data validity using checksum
chksum =rsdata2[0]+rsdata2[1]+rsdata2[2]+rsdata2[3];
if (chksum != rsdata2[4] ) {rsdata[0]=0;rsdata[1]=0;rsdata[2]=0;}
else { for (i=0;i<=2;i++){rsdata[i]=rsdata2[i+1]-128;}} } ct --; if (ct == 0) {ct = TIMEOUT_PRESET; p=0; rsdata[0] = 0;rsdata[1] = 0;rsdata[2] = 0;} //control signal timeout //モータ回転方向(ビット7)と、速度値(ビット6-ビット0)に分離:10000000-11111111:逆回転0-127、00000000-01111111:正回転0-127 for (char i=0; i<=2; i++) { if (rsdata[i] & 0b10000000) portdata |= 0b00000010; //回転データ作成 else portdata |= 0b00000001; //portdata:回転方向データの設定 portdata <<= 2; } //ここから計算 //モータ:PFM portdata2 = 0; // モーターをon/offデータの作成:回転方向データをportdata2でon/offさせる。 for (char i=0; i<=2; i++) { c[i] += (rsdata[i] & STEPFACTOR); //rsdataの値を用いてカウントアップすることで、桁上がりの頻度を制御する。 // if (CARRY) portdata2 |= 0b00000011; //桁上がりを利用してonoff判定。桁上がりがあった場合はON else portdata2 &= 0b11111100; //桁上がり無しの場合OFF portdata2 <<= 2; } portdata &= portdata2; //ポートに出力するデータの作成 portdata2 = portdata & 0b11000000;//portdata2を再利用してporta用データ作成(RB1,2はシリアル通信機能を有効にすると使えない) //portdata2 >>= 6; RA0:1使用
portdata <<= 2; PORTB &= 0b00000011; PORTA &= 0b00111111; PORTB |= portdata; //実際に出力 PORTA |= portdata2; DELAY_LOOP1; } } void interrupt isr_ser(void) { if (RCIF) { while (RCIF) { rsdata2[p] = RCREG; if (p != 0) p++; if ((p ==0) && (rsdata2[p] == 0xaa)) {p++; ct = TIMEOUT_PRESET;} if (p > 4) {p=0; buffull=1;}
if (FERR) {CREN=0;rsdata2[p] = 0; p=0;CREN=1;}}
}
}
追記2011/09/01
プログラムのHEXファイル(送信側) (受信側)
プロジェクトのzipファイル(送信側)(受信側)
(MPLAB8以前のバージョンでは、いくつか警告出るかもかもしれません。)
最近のMPLAB、7台後半のバージョンからだったか、日本語が含まれるディレクトリーに
ファイル置いてあっても使えるようです。