AD9830接続で挫折し、si5351aに切り替え、エアバンド用受信機局発を作ろうとしています。
秋月電子から部品が届きました。接続図に従い、PIC16F1829基板とつなぎます。
こうした際、配線確認もかね、i2cスキャンプログラムを流すことにしています。
i2cスキャンプログラムとは後で示すように、i2cアドレスを順繰りに出し、ack応答あるかを見るプログラムです。
oxC0で応答があり、無事動きました。
ところが、その後がいけません。i5351aの周波数設定プログラムを流すと、つながらない。
以前にPIC16F1829でMSSP2を使おうとしたらどうしても動かなくて、MSSP1に切り替えて使いましたが、再発です。原因追求中です。
i2cスキャンのプログラムです。
/* * File: newmain.c * Author: nobcha * Created on 2018/01/03, 18:01 */ /************************************************* MSSP i2c SCAN TEST of PIC12F1829 By nobcha all right reserved Ver 1.0 07/08/2012 for i2c peripheral TEST Ver 2.0 08/31/2012 for 1827 Ver 3.0 10/05/2014 for 1829 11/25/2014 MSSP2 is OK * 01/06/2018 MPLAB X transfered OK PIC12F1829 + LCD + charge pumping minus volt PIN Assign RA0:LCD RS bit(RS)はRA0に接続 RA1:LCD EN bit (enable)はRA1に接続 RA2: not used T0CKI:F-in RA3:RESET_sw : MCLR RB4:MEM_sw : SW2 RB5:SDA2 MSSP2 RB6:Heart beat LED RB7:SCL2 MSSP2 RC0: not used Toggle Prescaler:CNT DISABLE RC2-5:SC1602は4ビットモードとし、RC2-5で接続 RC6: Charge pump source:CCP4 RC7: Down_sw SW3 SC1602 pin connection via 4bit mode #1 Vdd=3V #2 Vss=GND #3 LCD contrust center of 10k VOL minus V #4 RS RA0 #5 R/W GND #6 EN RA1 #11-14 DATA RC2-5 OSC INT 16MHz Development Circumstance: MPLAB X IDE V2.20 ************************************************* */ #define _XTAL_FREQ 16000000 #define PIC_CLOCK 1600000 #include <stdio.h> #include <stdlib.h> #include <htc.h> #include "lcd.h" #include "mssp2_i2c.h" #define HEART_BEAT LATB6 #define UP_SW PORTBbits.RB4 // SW2 // CONFIG1 #pragma config FOSC = INTOSC // Oscillator Selection INT: device clock supplied to CLKIN pin) #pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled) #pragma config PWRTE = OFF // Power-up Timer Enable (PWRT disabled) #pragma config MCLRE = ON // MCLR Pin Function Select (MCLR/VPP pin function is RA3) #pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled) #pragma config CPD = OFF // Data Memory Code Protection (Data memory code protection is disabled) #pragma config BOREN = OFF // Brown-out Reset Enable (Brown-out Reset disabled) #pragma config CLKOUTEN = ON // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin) #pragma config IESO = OFF // Internal/External Switchover (Internal/External Switchover mode is disabled) #pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled) // CONFIG2 #pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off) #pragma config PLLEN = OFF // PLL Enable (4x PLL disabled) #pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset) #pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.) #pragma config LVP = OFF // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming) // proto void itostring(char , unsigned int , char* ); void mssp_init(void); unsigned char i2c_scan(unsigned char); // display data unsigned char Msg1[17] = "i2c SCAN test "; unsigned char Msg2[6] = "ADDR "; unsigned char Msg3[5] = "ack "; unsigned char Msg4[4] = " "; unsigned char Msg5[10] = " "; void main(void) { unsigned char i; /* INITIALIZE REGISTER */ OSCCON = 0b01111000; // Set 16MHz LATA = 0b00000000; // Clear TRISA = 0b00111100; // LATA INPUT RA4,5:SW,3:int,2:SW LATB = 0b00000000; // LATB RESET TRISB = 0b10110000; // LATB INPUT RB7:SCL2,5:SDA2,4:SW2 LATC = 0b00000000; // LATC RESET TRISC = 0b10000011; // LATC INPUT RC7:SW3,0,1:SHT ANSELA = 0b00000000; // All degital ANSELB = 0b00000000; ANSELC = 0b00000000; CM1CON0 = 0b00000111; // No using compalator CM2CON0 = 0b00000111; // No using compalator OPTION_REG = 0b10100100; // INTEDG 0,TOCS T0CKI 1,ToSE0,PSA TIMER0,1/32 INTCON=0; // INT off T1CON = 0; // Timer1 off // To generate minus voltage for LCD with 3V supply // CCP4 PWM initializing (83.8KHz on RB3 @16MHz) CCP4CON = 0b00001111; // use PWM mode CCPR4L = 0x0c; // duty is 50% CCPTMRS = 0; // Select TMR2 // TMR2 initilizing T2CON = 0b00000100; // POSTSCALE 1:1 ,TMR2 ON , PRESCALE 1:1 PR2 = 0x17; // resolution is 6.5bit mode TMR2ON = 1; // TMR2 start __delay_ms(200); __delay_ms(200); mssp_init(); // MSSP initialize lcd_init(); // LCD initialize continue HEART_BEAT = 1; // LED off while(1) { __delay_ms(100); HEART_BEAT ^= 1; // Heart beat LED upset lcd_goto(0x00); // Move cursor 1st line lcd_puts(Msg1); // Display test message i=2; while(i){ lcd_goto(0x40); // Move cursor to 2nd line lcd_puts(Msg2); // i2c addr message itostring(2,i,Msg4); // convert i to ASCII lcd_puts(Msg4); // SCAN ADD if(i2c_scan(i)==0){ // If detect ack,displaying addr lcd_puts(Msg3); itostring(2,i,Msg4); lcd_puts(Msg4); while(UP_SW) ; // Waiting SW1 PUSH CHECK __delay_ms(400); } else lcd_puts(Msg5); i=i+2; __delay_ms(100); HEART_BEAT ^= HEART_BEAT; // Heart beat LED upset } __delay_ms(500); // 0.5s waiting } } /*************************************** * Converting 2/4 hex to ASCII ****************************************/ void itostring(char digit, unsigned int data, char *buffer) { char i; // digit:2 or 4 buffer += digit; // last data for(i=digit; i>0; i--) { // buffer--; // *buffer = (data & 0xF) + '0'; // ASCII code if(*buffer>0x39) *buffer=*buffer+7; data = data >> 4; // next hex } } /*************************************** * MSMSSP2 initialize ****************************************/ void mssp_init(void){ // Assign MSSP SDA2 & SCL2 except for RX & TX // APFCON0 = 0x80; // Assign RX on RC5 instead of RB5 // SSP2CON1 REGISTERS SSP2CON1bits.SSPEN = 1; //Enables Serial Port Mode SSP2CON1bits.SSPM3 = 1; ///////// SSP2CON1bits.SSPM2 = 0; //I2C Master Mode SSP2CON1bits.SSPM1 = 0; // clock= Fosc/(4*(SSP2ADD+1)) SSP2CON1bits.SSPM0 = 0; //////// // SSP2CON2 REGISTERS SSP2CON2 = 0x00; // SSP2CON3 REGISTERS SSP2CON3 = 0x00; // SSP2STAT REGISTERS SSP2STATbits.SMP = 1; // SLEW RATE non SSP2STATbits.CKE = 1; //SMBus Specific Inputs Enabled //SSP2ADD = 0x19; //~75kHz SSP2ADD = 0x13; //~100kHz //SSP2ADD = 0x07; //~400kHz //SSP2ADD = 0x50; } /*************************************** * i2c address scanning test ****************************************/ unsigned char i2c_scan(unsigned char data){ unsigned char ack_data; i2c_start(); // start condition i2c_write(data); // addr & wite mode ack_data=i2c_readack(); // if ack:0 i2c_stop(); return (ack_data); }
MSSP制御関数です。プロトタイプ宣言のmssp2_i2c.hは必要です。
#define _LEGACY_HEADERS #include <htc.h> #include "mssp2_i2c.h" #define TRUE 0x0; #define FALSE 0x1; /************************************************** * MSSP使用マスターモード専用I2C関数 by nobcha * 教育・ホビー用. 営利目的・商用への利用は禁止 * 詳しいタイミングはNXPの資料やPICドキュメント * 参照のこと * 09/25/2011 * 10/05/2014 rewrite for MSSP2 ************************************************** */ /* * msspはSDAとSCL信号をスタート状態にします * 衝突有るとMSSPはリセットされる */ void i2c_start(void){ SSP2CON2bits.SEN = 1; // SSP1CON2:0 initiate I2C START condition while (SSP2CON2bits.SEN == 1); // wait until START bit finishes } /* * msspはSDAとSCL信号をRESTART状態にします * 衝突有るとBCL1IFが立つ */ void i2c_restart( void) { SSP2CON2bits.RSEN = 1; // SSP1CON2:1 Repeated Start while (SSP2CON2bits.RSEN==1); } /* 関数の説明 * DATAをSSP1BUFに書きスレーブに転送かける * 転送中はR_nWが1になっている */ void i2c_write( unsigned char DataByte ){ SSP2BUF = DataByte; while (SSP2STATbits.R_nW == 1); } /* 関数の説明 * 受信可にしてDATAを待つ。 * RSEN0になったら、SSP2BUFのデータを読み持って返る */ unsigned char i2c_read( void) { SSP2CON2bits.RCEN = 1; // SSP1CON2:3 Receive enable while (SSP2CON2bits.RCEN == 1); return SSP2BUF; } /* 関数の説明 * msspはSDAとSCL信号をstop状態にします * PENが0になったら、かえる。衝突あるとBCL1IFが立つ */ void i2c_stop( void) { SSP2CON2bits.PEN = 1; // SSP1CON2:2 initiate I2C STOP condition while (SSP2CON2bits.PEN); } /* 関数の説明 * ACK(ACKDT:0)かNACK(ACKDR:1)を送る * ACKENしたらかえる。 */ void i2c_sendack(unsigned char status) { SSP2CON2bits.ACKDT = status; // SSP1CON2:5 set to ACK:0,NACK:1 SSP2CON2bits.ACKEN = 1; // SSP1CON2:4 initiate I2C ACK condition while (SSP2CON2bits.ACKEN); // wait until ACK sequence is over } /* 関数の説明 * ACK(ACKDT:0)かNACK(ACKDR:1)をチェックする * ACK(ACKSTAT:0)かNACK(ACKSTAT:1)でかえる。 */ unsigned char i2c_readack(void) { if (SSP2CON2bits.ACKSTAT == 0) { return 0; // ACK detected } else { return 1; // ACK not detected } } /* 関数の説明 * 指定アドレスにWRITEモードでアドレスを書く * ACK有ればTRUEで、無ければFALSEでかえる */ unsigned char i2c_writeto(unsigned char address){ i2c_start(); i2c_write(address | 0x0); if(i2c_readack()) return TRUE; return FALSE; } /* 関数の説明 * 指定アドレスにREADモードでアドレスを書く * ACK有ればTRUEで、無ければFALSEでかえる */ unsigned char i2c_readfrom(unsigned char address){ i2c_start(); i2c_write(address | 0x1); if(i2c_readack()) return TRUE; return FALSE; }
ホームページではまとめて記載。