FC2カウンター FPGAの部屋 PIC16F1825 の使い方3(I2C 機能、ポーリング編)
fc2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

PIC16F1825 の使い方3(I2C 機能、ポーリング編)

PIC16F1825 の使い方3(I2C 機能、割り込み編)”の続き。

PIC マイコンの PIC16F1825 を使うことになったので、使い方の覚書を書いておく。
前回は、I2C 機能を割り込みで使用したが、I2C Read を連続して行うと 1 分くらいで止まってしまうので、I2C をポーリングで書き直した。

ポーリングを使用した acc3_uart.c を示す。
このポーリング編のライブラリ・コードは”【PIC】I2C通信のやり方”のライブラリのレジスタを変更して引用している。

/*
 * File:   acc3_uart.c
 * Author: ono
 *
 * Created on 2021/02/03, 11:09
 */
 // "【PIC】I2C通信のやり方”のライブラリを引用している
 //  https://rikeden.net/?p=36

#include <xc.h>
#include <stdint.h>

#pragma config FOSC = INTOSC
//#pragma config WDTEN = OFF
#pragma config LVP = OFF
#pragma config PWRTE = ON

unsigned char chr;
unsigned int n = 0;

void Delay(unsigned int m)
{
    for(n=0;n<m;n++);       //Delay
}

void I2C_Master_Wait();
void I2C_Master_Start();
void I2C_Master_RepeatedStart();
void I2C_Master_Stop();
void I2C_Master_Write(uint8_t d);
uint8_t I2C_Master_Read(uint8_t a);
void acc_sensor_write(uint8_t dev_addr, uint8_t reg_addr, uint8_t write_data);
void acc_sensor_grecv(uint8_t dataX[3], uint8_t dataY[3], uint8_t dataZ[3]);
uint8_t acc_sensor_data_ready(uint8_t dev_addr);
uint8_t acc_sensor_read_byte(uint8_t dev_addr, uint8_t reg_addr);
void acc_sensor_read_3bytes(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data);

void main( void )
{
    OSCCON = 0b11110000; // 4x PLL enable, 8MHz or 32MHz, FOSC
    OSCTUNE = 0x00;
    
    TRISA = 0;
    TRISC = 0x23; // SCL, SDA, UART RX is input setting.
    ANSELA = 0;
    ANSELC = 0;

    //I2C
    SSP1ADD   = 19;     //speed 400KHz
    //SSP1ADD   = 0x4F; //speed 100KHz
    SSP1STAT = 0b10000000; // 400kHz
    SSP1CON1 = 0b00101000;  //SSP1EN=1, Master mode
    SSP1CON2 = 0b00000000;
    SSP1CON3 = 0b00000000;
    //SSP1IE = 1;
    //SSP1IF = 0;
    
    // UART
    BAUDCON = 0; // BRG16=0: 8bit counter mode
    SPBRGL = 3; // SYNC=0, BRGH=1, BRG16=0, 500000bps
    TXSTA = 0b00100100; // TXEN=1, SYNC=0, BRGH=1
    RCSTA = 0b10010000; // SPEN=1, CREN=1
    //INTCON = 0b11000000; // GIE=1, PEIE=1
    RCIE = 1;
    RCIF = 0;
    PEIE = 1;
    GIE = 1;

     /*while(1){
        while(TRMT == 0);
        TXREG = 0x55;
              
        Delay(50);
    } */
    
    uint8_t dataX[3], dataY[3], dataZ[3];
    uint8_t count=0, count_b;
    
    /*while(1){
        acc_sensor_write(0x3a, 0x2c, 0x83); // I2C speed is Hi speed, +-8g
        Delay(500);
    }*/
    
    acc_sensor_write(0x3a, 0x2c, 0x83); // I2C speed is Hi speed, +-8g
    
    acc_sensor_write(0x3a, 0x1e, 0x00); // OFFSET_X_H
    acc_sensor_write(0x3a, 0x1f, 0x00); // OFFSET_X_L
    acc_sensor_write(0x3a, 0x20, 0x00); // OFFSET_Y_H
    acc_sensor_write(0x3a, 0x21, 0x00); // OFFSET_Y_L
    acc_sensor_write(0x3a, 0x22, 0x00); // OFFSET_Z_H
    acc_sensor_write(0x3a, 0x23, 0x00); // OFFSET_Z_L
    
    acc_sensor_write(0x3a, 0x2d, 0x00); // stanby clear
    
    while(1){
        while((acc_sensor_data_ready(0x3b) & 0x01) == 0);
        //acc_sensor_read_3bytes(0x3b, 0x08, dataX);
        acc_sensor_grecv(dataX, dataY, dataZ);
        Delay(1000);
    }
    
}

void interrupt RX_int(void){
    if(RCIF == 1){
        RCIF = 0;
        chr = RCREG;
        if(RCREG != 0x55)
            return;
              
        while(TRMT == 0);
        TXREG = chr + 1;
    }
}

void acc_sensor_write(uint8_t dev_addr, uint8_t reg_addr, uint8_t write_data){
    I2C_Master_Start();
    I2C_Master_Write(dev_addr);
    I2C_Master_Write(reg_addr);
    I2C_Master_Write(write_data);
    I2C_Master_Stop();
}

void acc_sensor_grecv(uint8_t *dataX, uint8_t *dataY, uint8_t *dataZ){
    while((acc_sensor_data_ready(0x3b) & 0x01) == 0);
    
    acc_sensor_read_3bytes(0x3b, 0x08, dataX);
    acc_sensor_read_3bytes(0x3b, 0x0b, dataY);
    acc_sensor_read_3bytes(0x3b, 0x0e, dataZ);
}

uint8_t acc_sensor_data_ready(uint8_t dev_addr){
    return(acc_sensor_read_byte(dev_addr, 0x04));
}

uint8_t acc_sensor_read_byte(uint8_t dev_addr, uint8_t reg_addr){
    uint8_t data;
    
    I2C_Master_Start();
    I2C_Master_Write(dev_addr & 0xFE);
    I2C_Master_Write(reg_addr);
    I2C_Master_RepeatedStart();
    I2C_Master_Write(dev_addr | 0x01);
    data = I2C_Master_Read(1);
    I2C_Master_Stop();
    return(data);
}
void acc_sensor_read_3bytes(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data){
    I2C_Master_Start();
    I2C_Master_Write(dev_addr & 0xFE);
    I2C_Master_Write(reg_addr);
    I2C_Master_RepeatedStart();
    I2C_Master_Write(dev_addr | 0x01);
    data[0] = I2C_Master_Read(0);
    data[1] = I2C_Master_Read(0);
    data[2] = I2C_Master_Read(1);
    I2C_Master_Stop();
}
void I2C_Master_Wait(){
  while ((SSP1STAT & 0x04) || (SSP1CON2 & 0x1F)); //Transmit is in progress
}
void I2C_Master_Start(){
  I2C_Master_Wait();    
  SSP1CON2bits.SEN = 1;           //Initiate start condition
}
void I2C_Master_RepeatedStart(){
  I2C_Master_Wait();
  SSP1CON2bits.RSEN = 1;          //Initiate repeated start condition
}
void I2C_Master_Stop(){
  I2C_Master_Wait();
  SSP1CON2bits.PEN = 1;           //Initiate stop condition
}
void I2C_Master_Write(uint8_t d){
  I2C_Master_Wait();
  SSP1BUF = d;                    //Write data to SSP1BUF
}
uint8_t I2C_Master_Read(uint8_t a){
  uint8_t temp;
  I2C_Master_Wait();
  SSP1CON2bits.RCEN = 1;
  I2C_Master_Wait();
  temp = SSP1BUF;                 //Read data from SSP1BUF
  I2C_Master_Wait();
  SSP1CON2bits.ACKDT = a;         //Acknowledge bit    1:NACK  0:ACK
  SSP1CON2bits.ACKEN = 1;         //Acknowledge sequence
  return temp;
}


acc_sensor_read_byte(dev_addr, 0x04)

の 1 バイトの Read のトランザクションを示す。
PIC_5_210317.jpg
PIC_6_210317.jpg

0x07 が Read できた。

次に、

acc_sensor_read_3bytes(0x3b, 0x08, dataX);

の 3 バイト Read トランザクションを示す。
PIC_2_210317.jpg
PIC_3_210317.jpg
PIC_4_210317.jpg

0x00, 0x1F, 0x70 が Read できた。
しかしやはり、連続 Read していると 1 分くらいで止まってしまう。。。
  1. 2021年03月19日 03:36 |
  2. PIC
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック URL
https://marsee101.blog.fc2.com/tb.php/5182-3eb3dd7c
この記事にトラックバックする(FC2ブログユーザー)