nobcha23の日記

PICマイコンやArduinoを使う電子回路遊びを紹介します

i2cポートの動作をi2cインタフェイスLCDと接続して確かめる

エアバンド用の受信機用局部発振器を作ろうとしてDDSから始まり、
うまくいかなかったので、si5351aを使用することにして実験をしています。

ところが、PIC16F1829基板を使用したsi5351aのi2c接続でとらぶっています。

以前PIC16F1829のMSSP2接続がうまくいかなかったことがあり、まずはi2c接続が
うまくいっているのかを確かめることにしました。

秋月電子通商のsi5351a基板のi2c信号配置とi2c接続小型キャラクLCDモジュールの
信号配置が同じなことを知り、si5351a用に配線したコネクタにつなぎ変えてみます。
[スイッチサイエンス] I2C接続の小型LCD搭載ボード(3.3V版)

実験用のソフトとしてはi2cスキャンプログラムということにして、従来4ビット
LCD表示に加え、i2c接続LCDへの表示も移植してみました。

i2c接続LCDは以前2種類試したことがあり、今回のモジュールはSUNLINK社のものと
類似していたので割と簡単につなげました。



ということでMSSP2の動作はOKが確認され、次はsi5351aへのパラメータ設定値を
疑いデバッグしないといけません。

今回の液晶表示改造のi2c SCAnプログラムのメインは次の通り。

/* 
 * File:   main_i2clcd.c
 * Author: nobcha
 * Created on 2018/02/10, 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
 * 01/07/2018 PIC16F1829 MSSP2 OK
 * 02/10/2018 i2C LCD display

   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_4bit_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 16000000

#include <stdio.h>
#include <stdlib.h>
#include <htc.h>
#include "lcd.h"
#include "mssp2_i2c.h"
#include "lcd_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
    
    lcd_i2c_init();         // i2c LCD initialize
	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
        
		lcd_i2c_goto(0x00);			// Move cursor 1st line
		lcd_i2c_puts(Msg1);			// Display test message        

		i=2;
		while(i){
			lcd_goto(0x40);         // Move cursor to 2nd line
			lcd_puts(Msg2);         // i2c addr message
            
			lcd_i2c_goto(0x40);		// Move cursor to 2nd line
			lcd_i2c_puts(Msg2);		// i2c addr message            
            
			itostring(2,i,Msg4);    // convert i to ASCII
			lcd_puts(Msg4);         // SCAN ADD
            
            lcd_i2c_puts(Msg4);

			if(i2c_scan(i)==0){     // If detect ack,displaying addr
				lcd_puts(Msg3);
				itostring(2,i,Msg4);
				lcd_puts(Msg4);

                
				lcd_i2c_puts(Msg3);                
				lcd_i2c_puts(Msg4);
                
				while(UP_SW) ;      // Waiting SW1 PUSH CHECK
				__delay_ms(400);
			}
			else{
                lcd_puts(Msg5);
                lcd_i2c_puts(Msg5);
            }
            
			i=i+2;
			__delay_ms(100);
		HEART_BEAT ^= HEART_BEAT;	// Heart beat LED upset
		}

		__delay_ms(500);		// 0.5s waiting
	}
}

/***************************************
* 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);
}

/***************************************
* 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    = 0x36;    		//~75kHz @16MHz

}


i2c接続液晶用部は次です。

// For i2c LCD(AQM1602XA-RN-GBW)
//  i2c LCD on PIC16F1829 mssp2 port
// 2018.02.10
// OK
// 

#define _XTAL_FREQ 16000000
#define PIC_CLOCK 16000000
#define LCD_AD 0x7C

#include	<htc.h>
#include    "lcd_i2c.h"
#include    "mssp2_i2c.h"

void    lcd_i2c_cmd(unsigned char cmd){
    i2c_writeto(LCD_AD);        // AQM1602XA-RN-GBW=0x7C
    i2c_write(0x00);            // RS:0 command mode set
    i2c_write(cmd);             //
    i2c_stop();
    if((cmd == 0x01)||(cmd == 0x02))
        __delay_ms(2);
    else
        __delay_us(40);
    }

void    lcd_i2c_data(unsigned char data1){

    i2c_writeto( LCD_AD );
    
    i2c_write(0x40);
    i2c_write(data1);
    i2c_stop();
    }



void	lcd_i2c_goto(unsigned char cursor){
    lcd_i2c_cmd(0x80 | cursor);    
}

void	lcd_i2c_puts(char* ptr){
    while (*ptr !=0){
        lcd_i2c_data(*ptr++);
    }
}



void    lcd_i2c_init(){
    lcd_i2c_cmd(0x38);
    __delay_us(50);
    lcd_i2c_cmd(0x39);
    __delay_us(50);
    lcd_i2c_cmd(0x14);
    __delay_us(50);
    lcd_i2c_cmd(0x73);
    __delay_us(50);    
    lcd_i2c_cmd(0x56);
    __delay_us(50);
    lcd_i2c_cmd(0x6C);
    __delay_ms(250);  
    lcd_i2c_cmd(0x38);
    __delay_us(50);
    lcd_i2c_cmd(0x01);
    __delay_us(50);    
    lcd_i2c_cmd(0x0C);
    __delay_us(50);    
    
}

またヘッダは次になります。

/* 
 * File:   lcd_i2c.h
 * Author: nobcha
 * Created on 2018/02/10, 19:56
 */

#include	<htc.h>

void	lcd_i2c_goto(unsigned char);		// Move cursor
void	lcd_i2c_puts(char*);

void    lcd_i2c_cmd(unsigned char);
void    lcd_i2c_data(unsigned char);
void    lcd_i2c_init();

色々な情報はホームページにまとめています。


電子工作のための PIC16F1ファミリ活用ガイドブック

KKmoon レシーバーキット エアバンドラジオ レシーバー DIYキット 航空バンドレシーバー