プロポソースコード
詳細はこちらをご覧ください(YouTube,公式ホームページ)→(準備中)
Compiler:XC8
C version:C90
// PIC18F23K22 Configuration Bit Settings
// 'C' source line config statements
// CONFIG1H
#pragma config FOSC = INTIO67 // Oscillator Selection bits (Internal oscillator block)
#pragma config PLLCFG = OFF // 4X PLL Enable (Oscillator used directly)
#pragma config PRICLKEN = ON // Primary clock enable bit (Primary clock enabled)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)
// CONFIG2L
#pragma config PWRTEN = ON // Power-up Timer Enable bit (Power up timer enabled)
#pragma config BOREN = SBORDIS // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware only (SBOREN is disabled))
#pragma config BORV = 190 // Brown Out Reset Voltage bits (VBOR set to 1.90 V nominal)
// CONFIG2H
#pragma config WDTEN = OFF // Watchdog Timer Enable bits (Watch dog timer is always disabled. SWDTEN has no effect.)
#pragma config WDTPS = 32768 // Watchdog Timer Postscale Select bits (1:32768)
// CONFIG3H
#pragma config CCP2MX = PORTC1 // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
#pragma config PBADEN = ON // PORTB A/D Enable bit (PORTB<5:0> pins are configured as analog input channels on Reset)
#pragma config CCP3MX = PORTB5 // P3A/CCP3 Mux bit (P3A/CCP3 input/output is multiplexed with RB5)
#pragma config HFOFST = OFF // HFINTOSC Fast Start-up (HFINTOSC output and ready status are delayed by the oscillator stable status)
#pragma config T3CMX = PORTC0 // Timer3 Clock input mux bit (T3CKI is on RC0)
#pragma config P2BMX = PORTB5 // ECCP2 B output mux bit (P2B is on RB5)
#pragma config MCLRE = INTMCLR // MCLR Pin Enable bit (RE3 input pin enabled; MCLR disabled)
// CONFIG4L
#pragma config STVREN = ON // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = ON // Single-Supply ICSP Enable bit (Single-Supply ICSP enabled if MCLRE is also 1)
#pragma config XINST = OFF // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))
// CONFIG5L
#pragma config CP0 = OFF // Code Protection Block 0 (Block 0 (000200-000FFFh) not code-protected)
#pragma config CP1 = OFF // Code Protection Block 1 (Block 1 (001000-001FFFh) not code-protected)
// CONFIG5H
#pragma config CPB = OFF // Boot Block Code Protection bit (Boot block (000000-0001FFh) not code-protected)
#pragma config CPD = OFF // Data EEPROM Code Protection bit (Data EEPROM not code-protected)
// CONFIG6L
#pragma config WRT0 = OFF // Write Protection Block 0 (Block 0 (000200-000FFFh) not write-protected)
#pragma config WRT1 = OFF // Write Protection Block 1 (Block 1 (001000-001FFFh) not write-protected)
// CONFIG6H
#pragma config WRTC = OFF // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected)
#pragma config WRTB = OFF // Boot Block Write Protection bit (Boot Block (000000-0001FFh) not write-protected)
#pragma config WRTD = OFF // Data EEPROM Write Protection bit (Data EEPROM not write-protected)
// CONFIG7L
#pragma config EBTR0 = OFF // Table Read Protection Block 0 (Block 0 (000200-000FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF // Table Read Protection Block 1 (Block 1 (001000-001FFFh) not protected from table reads executed in other blocks)
// CONFIG7H
#pragma config EBTRB = OFF // Boot Block Table Read Protection bit (Boot Block (000000-0001FFh) not protected from table reads executed in other blocks)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#include <xc.h>
#define _XTAL_FREQ 64000000
int wait = 1;
char ReadData1[5]; //受信データ格納先
int ReadCount1 = 0; //受信バイト数カウント
int ReadError1 = 0; //受信エラーフラグ
int ReadErrorCount1 = 0; //連続受信エラー回数
int cal_center[4]; //キャリブレーション
int speed;
int speed_max = 127; //127以下
float motion_range = 30; //サーボの可動域の半分(度)0?90 要調整
float motion_ratio; //(サーボの可動域 × 1000) ÷ ジョイスティックの可動域
int ang; //サーボの角度
void __interrupt () Interrupt();
void PICSetup();
void SerialSetup();
void TimerSetup();
void InterruptSetup();
void JoystickSetup();
/*unsigned*/ int adconv(int);
void SerialWrite1(int,int,int,int,int);
int main(){
unsigned int num;
PICSetup();
SerialSetup();
TimerSetup(); //一時的後で消す!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1
InterruptSetup();
JoystickSetup();
motion_ratio = (motion_range*2)/1024;
while(1){
if(!PORTCbits.RC0){ //キャリブレーション
__delay_ms(100); //チャタリング防止
while(!PORTCbits.RC0); //指を放すまで待つ
__delay_ms(500); //チャタリング防止
cal_center[0] = adconv(0); //縦
cal_center[1] = adconv(1); //横
}
if(!PORTCbits.RC1){ //キャリブレーション
__delay_ms(100); //チャタリング防止
while(!PORTCbits.RC0); //指を放すまで待つ
__delay_ms(500); //チャタリング防止
cal_center[2] = adconv(2); //縦
cal_center[3] = adconv(3); //横
}
RC1IE = 1; //受信割り込み許可
SerialWrite1(speed,ang,0,0,127);
//SerialWrite1(adconv(0)/4,adconv(1)/4,adconv(2)/4,adconv(3)/4,0);
__delay_ms(20); //タイムアウトまで待つ
RC1IE = 0; //受信割り込み禁止
if(ReadError1 == 1 || !(ReadCount1 == 4)){ //受信エラーがある、もしくは受信データ数がおかしかったら
ReadError1 = 0; //エラーフラグをリセット
ReadErrorCount1++; //連続受信エラー回数
}else{
//データ入力
ReadErrorCount1 = 0; //連続受信エラー回数リセット
}
ReadCount1 = 0; //受信回数リセット
wait = 1; //待機状態にする
speed = (adconv(2) - cal_center[2])/4; //8bit符号付き(-127?128)に変換
if(speed > -5 && speed < 5){ //speedの絶対値が5未満のときは0とみなす
speed = 0;
}
if(speed > speed_max){ //最大より大きな値の場合
speed = speed_max;
}
if(speed < speed_max*(-1)){
speed = speed_max*(-1);
}
ang = (adconv(1) - cal_center[1])/4;
if(ang > 125){
ang = 125;
}
if(ang < -125){
ang = -125;
}
while(wait); //待機
// __delay_ms(80); //一時的なもの!必ず消すこと!!!!!!!!!!!!!!!!!!!!
}
}
void __interrupt () Interrupt(){
GIE = 0;
if(T0IF == 1){
wait = 0; //待機解除
TMR0 = 59286; //タイマー0レジスタの初期化 100msで割り込み
}
if( FERR1 || OERR1 ){ //uartエラー処理
CREN1 = 0;
NOP();
CREN1 = 1;
while(FERR1){
int trush;
trush = RCREG1;
}
ReadError1 = 1;
}else if(RC1IF == 1){
if(ReadCount1 <= 4){//受信フラグが立ち、受信した回数が5回以下なら
ReadData1[ReadCount1] = RCREG1 ; // レジスタからデータを受信
ReadCount1++;
}else{
int trush;
trush = RCREG1;
ReadError1 = 1;
}
}
T0IF = 0; //フラグをリセット
RC1IF = 0;
GIE = 1;
}
void PICSetup(){
OSCCON = 0b01110000; //16MHz内部クロック使用
OSCTUNEbits.PLLEN = 1; //内部クロックをPLLで4逓倍 64MHz
ANSELA = 0b00001111; //AN0(2ピン)有効化
// ANSELA = 0; //一時的なもの!必ず消すこと!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ANSELB = 0b00000000;
ANSELC = 0b00000000;
TRISA = 0b00001111;
TRISB = 0b00000000;
TRISC = 0b10000011;
// TRISC = 0; //一時的なもの!必ず消すこと!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
LATA = 0b00000000;
LATB = 0b00000000;
LATC = 0b00000000;
ADCON0 = 0b00000001; //AN0から読み込む アナログ変換有効
ADCON1 = 0b00000000; //リファレンス電圧をVDDにする
ADCON2 = 0b10101001;
__delay_us(8);
}
void SerialSetup(){
TXSTA1 = 0b00100100;
RCSTA1 = 0b10010000;
BAUDCON1 = 0b00001000;
SPBRG1 = 0b10001010; //34 115200
SPBRGH1 = 0b00000000;
CREN1 = 1;
}
void TimerSetup(){
T0CON = 0b10000111; //タイマー0有効 16μsで1カウント
TMR0 = 59286; //タイマー0レジスタの初期化 100msで割り込み
}
void InterruptSetup(){
GIE = 1; //割り込み許可
PEIE = 1; //周辺機器の割り込み許可
TMR0IF = 0; //タイマー0フラグ初期化
TMR0IE = 1; //タイマー0割り込み許可
RC1IF = 0; //uart1フラグ初期化
}
void JoystickSetup(){
cal_center[0] = adconv(0);
cal_center[1] = adconv(1);
cal_center[2] = adconv(2);
cal_center[3] = adconv(3);
}
/*unsigned*/ int adconv(int num){
/*unsigned*/ int voltage;
ADCON0 = (num << 2) | 1;
GO_nDONE = 1; //AD変換開始
while(GO_nDONE);
voltage = ADRESH;
voltage = (voltage << 8) | ADRESL;
return voltage;
}
void SerialWrite1(int data0,int data1,int data2,int data3,int data4){
signed char WriteData1[5];
WriteData1[0] = (signed char)data0;
WriteData1[1] = (signed char)data1;
WriteData1[2] = (signed char)data2;
WriteData1[3] = (signed char)data3;
WriteData1[4] = (signed char)data4;
int i;
for (i = 0;i <= 4;i++){ //data0からdata4まで順番に送信
while(TX1IF == 0); //送信可能になるまで待つ
TXREG1 = WriteData1[i]; //iバイト目を送信
// __delay_ms(5);
}
/* while(TX1IF == 0); //送信可能になるまで待つ
TXREG1 = data0; //0バイト目を送信
__delay_us(1500);
while(TX1IF == 0); //送信可能になるまで待つ
TXREG1 = data1; //1バイト目を送信
__delay_us(1500);
while(TX1IF == 0); //送信可能になるまで待つ
TXREG1 = data2; //2バイト目を送信
__delay_us(1500);
while(TX1IF == 0); //送信可能になるまで待つ
TXREG1 = data3; //3バイト目を送信
__delay_us(1500);
while(TX1IF == 0); //送信可能になるまで待つ
TXREG1 = data4; //4バイト目を送信*/
}