ESCソースコード
詳細はこちらをご覧ください(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 = PORTC0 // 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> #include <stdio.h> #include <stdint.h> #include <string.h>
#define _XTAL_FREQ 64000000 #define DATA_SIZE (5) #define I2C_ACK 0x00 #define I2C_NACK 0xff #define ADRESS_PCA9685 0x80 // PCA9685 のデバイスアドレス
//#define SERVO_PULSE_MIN (500) #define SERVO_PULSE_MIN (1300)
//#define SERVO_PULSE_MAX (2400) #define SERVO_PULSE_MAX (1600)
int ReadCount;
int ReadFlag;
signed char ReadData[DATA_SIZE];
signed char SetData[DATA_SIZE];
signed char MoterSpeed;
int pulse_ratio = (SERVO_PULSE_MAX - SERVO_PULSE_MIN)/256;
void __interrupt () Interrupt();
void PICSetup();
void CCPSetup();
void InterruptSetup();
void SerialSetup();
void TimerSetup();
void I2C_setup();
void SerialWrite1(char,char,char);
void i2c_1_start();
void i2c_1_stop();
void i2c_1_write(uint8_t);
uint8_t i2c_1_CheckAck();
void write_PCA16(uint8_t,uint8_t,uint16_t);
void write_PCA8(uint8_t,uint8_t,uint8_t);
void init_servo();
void pos_servo(int,unsigned long);
void Moter();
int main(){
PICSetup();
CCPSetup();
InterruptSetup();
SerialSetup();
TimerSetup();
I2C_setup();
init_servo();
while(1){
MoterSpeed = SetData[0];
Moter();
pos_servo( 0,(unsigned long)((((int)SetData[1]*pulse_ratio)*(-1)) + ((SERVO_PULSE_MIN + SERVO_PULSE_MAX)/2)));
// __delay_ms(100);
}
}
void PICSetup(){
OSCCON = 0b01110000; //16MHz????????
OSCTUNEbits.PLLEN = 1; //???????PLL?4?? 64MHz
ANSELA = 0b00000000;
ANSELB = 0b00000000;
ANSELC = 0b00000000;
TRISA = 0b00000000;
TRISB = 0b00000000;
TRISC = 0b10011000;
LATA = 0b00000000;
LATB = 0b00000000;
LATC = 0b00000000;
}
void CCPSetup(){
CCPTMRS0 = 0b00000000; //CCP2 -> timer2
CCP2CON = 0b00001100; //PWM MODE
T2CON = 0b00000010; //TMR2?????? 1/16
TMR2 = 0; //TMR2COUNTER ???
CCPR2L = 0; //??????? ???
CCPR2H = 0;
PR2 = 249; //4000hz
TMR2ON = 1; //TMR2 START
}
void InterruptSetup(){
T0IF = 0; //タイマー0フラグ初期化
RC1IF = 0; //uart1フラグ初期化
SSP1IF = 0; //SSPフラグ初期化
BCL1IF = 0; //MSSPバス衝突フラグ初期化
GIE = 1; //割り込み許可
PEIE = 1; //周辺機器の割り込み許可
RC1IE = 1; //受信割り込み許可
T0IE = 1; //タイマー0割り込み許可
// SSP1IE = 1; //SSP割り込み許可
// BCL1IE = 1; //MSSPバス衝突割り込み許可
}
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 = 53036; //タイマー0レジスタの初期化 200msで割り込み
}
void I2C_setup(){
SSP1STAT = 0b10000000;
SSP1CON1 = 0b00101000;
SSP1CON3 = 0b00000000;
SSP1ADD = 159;
}
void __interrupt () Interrupt(){
GIE = 0;
if(T0IF){
TMR0 = 53036;
T0IF = 0;
}
if( FERR1 || OERR1 ){
CREN1 = 0;
NOP();
CREN1 = 1;
}
if(RC1IF){
ReadData[ReadCount] = RCREG1;
if(ReadData[ReadCount] == 127){
if(ReadCount == 4){
memcpy(SetData,ReadData,sizeof(ReadData));
ReadFlag = 1;
}
ReadCount = 0;
}else if(ReadCount >= 4){
ReadCount = 0;
}else{
ReadCount++;
}
RC1IF = 0;
}
GIE = 1;
}
void SerialWrite1(char data0,char data1,char data2){
char WriteData1[3];
WriteData1[0] = data0;
WriteData1[1] = data1;
WriteData1[2] = data2;
int i;
for (i = 0;i <= 2;i++){ //data0からdata4まで順番に送信
while(TX1IF == 0); //送信可能になるまで待つ
TXREG1 = WriteData1[i]; //iバイト目を送信
__delay_ms(5);
}
}
void i2c_1_start() {
// SSP1CON2レジスタのSENビットを1に設定すると
// スタートコンディションが生成される
// 発行が完了するとSSP1IFが1になるのでwhile文で待つ
SSP1IF = 0;
SSP1CON2bits.SEN = 1;
while (SSP1IF == 0) {}
SSP1IF = 0;
return;
}
void i2c_1_stop() {
// SSP1CON2レジスタのPENビットを1に設定すると
// ストップコンディションが生成される
// 発行が完了するとSSP1IFが1になるのでwhile文で待つ
SSP1IF = 0;
SSP1CON2bits.PEN = 1;
while (SSP1IF == 0) {}
SSP1IF = 0;
return;
}
void i2c_1_write(uint8_t data) {
// SSP1BUFに送信したいデータをセットすると、そのデータが送信される
// 発行が完了するとSSP1IFが1になるのでwhile文で待つ
SSP1IF = 0;
SSP1BUF = data;
while (SSP1IF == 0) {}
SSP1IF = 0;
return;
}
uint8_t i2c_1_CheckAck() {
uint8_t ackStatus;
if (SSP1CON2bits.ACKSTAT) {
ackStatus = I2C_NACK;
} else {
ackStatus = I2C_ACK;
}
return ackStatus;
}
void write_PCA16(uint8_t lowad,uint8_t reg,uint16_t data){
i2c_1_start();
i2c_1_write( ADRESS_PCA9685 + ( lowad << 1 ) ); // I2Cアドレス
i2c_1_write( reg ); // レジスタNo.
i2c_1_write( data & 0x00FF ); // 下位データ
i2c_1_write( data >> 8 ); // 上位データ
i2c_1_stop();
}
// I2Cデバイスへの8bitデータの書き込み
void write_PCA8(uint8_t lowad,uint8_t reg,uint8_t data ){
i2c_1_start();
i2c_1_write( ADRESS_PCA9685 + ( lowad << 1 ) ); // I2Cアドレス
i2c_1_write( reg ); // レジスタNo.
i2c_1_write( data ); // データ
i2c_1_stop();
}
void init_servo(){
int i,j;
// いったんスタンバイにする(プリスケーラ設定のため)
write_PCA8( 0, 0, 0x31 );
// プリスケーラ設定。分解能4us、周期20ms(周波数50Hz)!!デバイスごとに調整!!
write_PCA8( 0, 0xFE, 121 );
// MODE1設定 レジスタインクリメント、All-Call有効、アクティブ
write_PCA8( 0, 0, 0x21 );
// MODE2設定 トーテムポール出力設定
write_PCA8( 0, 1, 0x04 );
// パルス初期値書き込み(1500us)
j = 0x06;
for ( i = 0 ; i < 16 ; i++ ) {
write_PCA16( 0, j, 0 ); // パルススタート
j += 2;
write_PCA16( 0, j, 375 ); // パルスエンド
j += 2;
}
}
// サーボセット(サーボ位置をパルス幅で渡す)
void pos_servo(int id,unsigned long pos){
int i;
i = 8 + id * 4 ;
write_PCA16( 0, i, pos / 4 );
}
void Moter(){
if(MoterSpeed > 0){
PSTR2CON = 0b00000001;
CCPR2L = MoterSpeed*2;
}
if(MoterSpeed == 0){
PSTR2CON = 0b00000000;
CCPR2L = 0;
}
if(MoterSpeed < 0){
PSTR2CON = 0b00000010;
CCPR2L = MoterSpeed*(-2);
}
}
この記事が気に入ったらサポートをしてみませんか?