繁体   English   中英

试图了解I2C的Microchip PIC16LF15344外设引脚选择

[英]Trying to understand Microchip PIC16LF15344 peripheral pin selection for I2C

我一直在查看Microchip PIC16LF15344数据手册中的外设引脚选择,或者我读取不正确,或者文档中似乎有错误和不一致。 我想知道是否有人使用过该设备并且可以确认我的解释。

我正在尝试为PIC16LF15344编写代码以利用I2C接口。 我已经设法为PIC16LF1822编写了可以正常工作的I2C代码,但是到目前为止,我仍然无法使它在PIC16LF15344上正常工作,并且数据表中有一些令人困惑的文档需要清除。

这是对数据表的参考。

PIC16LF15344pinout说明表明,可以将I2C SDA功能分配给RC1RB6 同样, I2C SCL可以分配给RC0RB4 但是在Section 15.3 Bidirectional Pins有一个注意事项,如下所示。

可以通过PPS重新映射I2C SCLxSDAx功能。 但是,只有RB1RB2RC3RC4品脱实现了I2CSMBus特定的输入缓冲区( I2C模式禁用INLVL并设置特定于I2C阈值)。 如果将SCLxSDAx功能映射到其他某个引脚( RB1RB2RC3RC4除外),则将使用通用TTLST输入缓冲区(基于INLVL寄存器设置进行配置)。 因此,在大多数应用中,建议仅将SCLxSDAx引脚功能映射到RB1RB2RC3RC4引脚。

问题不仅在于注释似乎与引脚分配表中的描述冲突,而且还引用了引脚RB1RB2 ,这些引脚未出现在引脚分配表中的任何位置,即,它们似乎不存在本PIC 我看到了与RB1RB2类似的脚注,但在文档或表格的正文中均未记录。

当然,这肯定是一个文档错误,但是我无法在PIC16LF15324/44数据手册上找到当前的勘误表来更正此错误。 我读对了吗?

我尝试用PPSSCLSDA配置为引脚RC0RC1 ,因为这是它们在PCB ,但是我仍然无法使用与PIC16LF1822相同的软件来使I2C工作。 EUSART TX2RX2默认PPSRC0RC1 这是否意味着在使用SSP1CLKPPSSSP1DATPPSSCLSDA分配给RC0RC1之前,我需要使用TX2CKPPSRX2DTPPSEUSART分配移动到其他位置?

我将调查PCB其他潜在问题,但我想弄清楚这一点,然后再为工厂提交另一块PCB 无论如何,我都需要进行一些更改,因此我可能只需要在下一个版本中将SCLSDA连接到其PPS默认值,然后重试即可。

这是初始化代码:

OSCFRQbits.HFFRQ = 0b011; // Set internal HF oscillator frequency to 8 MHz
WPUA   = 0b00111111;    // Enable all weak pull-up resistors on port A
WPUB   = 0b11110000;    // Enable all weak pull-up resistors on port B
WPUC   = 0b11111100;    // Enable all weak pull-up resistors on port C except
                        //    RC0 and RC1 to be used as I2C SCL and SDA
TRISA  = 0b00110000;    // Set RA4 and RA5 as inputs
ANSELA = 0b00110000;    // Set RA4 and RA5 to analog
TRISB  = 0b00110000;    // Set RB6 and RB7 as inputs
ANSELB = 0b11000000;    // Set RB6 and RB7 as analog
TRISC  = 0b11111011;    // Set RC0, RC1, RC3, RC4, RC5, RC6, and RC7 as inputs
ANSELC = 0b11111000;    // Set RC3, RC4, RC5, RC6, and RC7 as analog
TX2CKPPS   = 0b01100;   // Use RB4 for TX2
RX2DTPPS   = 0b01110;   // Use RB6 for RX2
SSP1CLKPPS = 0b10000;   // Use RC0 as SCL
SSP1DATPPS = 0b10001;   // Use RC1 as SDA
SSP1CON1 = 0b00100110;  // SSPEN enabled, WCOL no collision, SSPOV no overflow,
                        // CKP low hold, SSPM I2C slave 7-bit

SSP1CON2 = 0b00000000;  // ACKSTAT received, RCEN disabled, RSEN disabled, 
                        // ACKEN disabled, ACKDT acknowledge, SEN disabled, 
                        // GCEN disabled, PEN disabled

SSP1CON3 = 0b00000000;  // BOEN disabled, AHEN disabled, SBCDE disabled, 
                        // SDAHT 100 ns hold, ACKTIM ackseq, DHEN disabled, 
                        // PCIE disabled, SCIE disabled

SSP1STAT = 0x00;
SSP1BUF  = 0x00;
SSP1MSK  = 0xff;
SSP1ADD  = I2C_SLAVE_ADDR << 1;
PIR3bits.SSP1IF = 0;    // Clear the SSP Interrupt flag
PIE3bits.SSP1IE = 1;    // Enable SSP Interrupts
INTCONbits.GIE = 1;     // Enable global interrupts
INTCONbits.PEIE = 1;    // Enable peripheral interrupts

您可能要处理几个问题。

所有默认的I2C引脚也都具有模拟功能。 确保将与I2C引脚关联的ANSBANSC位设置为数字操作。

上电复位选择I2C输入引脚分配的数据手册默认值时,默认情况下, I2C输出未分配给任何GPIO引脚。 您需要将SCLSDAI2C输出放置在正确的PPS映射寄存器中。

请注意,无论采用I2C主器件还是从器件实现,输入和输出功能都应映射到同一引脚。

这将有助于编辑问题并发布用于初始化I2C引脚和PPS映射寄存器的代码。

/*
 * File:   main.c
 *                             PIC16LF15354
 *                   +-------------:_:-------------+
 * 10K Pull-Up ->  1 : RE3/MCLR   ANB7/RX2/PGD/RB7 : 28 <> 
 *             <>  2 : RA0/ANA0   ANB6/TX2/PGC/RB6 : 27 <> RX2
 *             <>  3 : RA1/ANA1           ANB5/RB5 : 26 <>
 *             <>  4 : RA2/ANA2           ANB4/RB4 : 25 <> TX2
 *             <>  5 : RA3/ANA3           ANB3/RB3 : 24 <>
 *             <>  6 : RA4/ANA4      ANB2/SDA2/RB2 : 23 <>
 *             <>  7 : RA5/ANA5      ANB1/SCL2/RB1 : 22 <>
 *         GND ->  8 : VSS                ANB0/RB0 : 21 <>
 *             <>  9 : RA7/OSC1/ANA7           VDD : 20 <- 3v3
 *             <> 10 : RA6/OSC2/ANA6           VSS : 19 <- GND
 *        SCL1 <> 11 : RC0/ANC0       ANC7/RX1/RC7 : 18 <>
 *        SDA1 <> 12 : RC1/ANC1       ANC6/TX1/RC6 : 17 <>
 *             <> 13 : RC2/ANC2           ANC5/RC5 : 16 <> 
 *             <> 14 : RC3/SCL1/ANC3 ANC4/SDA1/RC4 : 15 <>
 *                   +-----------------------------:
 *                               DIP-28
 *
 * Created on January 4, 2019, 6:20 PM
 */


// PIC16LF15354 Configuration Bit Settings
#pragma config FEXTOSC = OFF    // External Oscillator mode selection bits (Oscillator not enabled)
#pragma config RSTOSC = HFINT32 // Power-up default value for COSC bits (HFINTOSC with OSCFRQ= 32 MHz and CDIV = 1:1)
#pragma config CLKOUTEN = OFF   // Clock Out Enable bit (CLKOUT function is disabled; i/o or oscillator function on OSC2)
#pragma config CSWEN = ON       // Clock Switch Enable bit (Writing to NOSC and NDIV is allowed)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (FSCM timer disabled)
#pragma config MCLRE = ON       // Master Clear Enable bit (MCLR pin is Master Clear function)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config LPBOREN = OFF    // Low-Power BOR enable bit (ULPBOR disabled)
#pragma config BOREN = OFF      // Brown-out reset enable bits (Brown-out reset disabled)
#pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (VBOR) set to 1.9V on LF, and 2.45V on F Devices)
#pragma config ZCD = OFF        // Zero-cross detect disable (Zero-cross detect circuit is disabled at POR.)
#pragma config PPS1WAY = OFF    // Peripheral Pin Select one-way control (The PPSLOCK bit can be set and cleared repeatedly by software)
#pragma config STVREN = ON      // Stack Overflow/Underflow Reset Enable bit (Stack Overflow or Underflow will cause a reset)
#pragma config WDTCPS = WDTCPS_31// WDT Period Select bits (Divider ratio 1:65536; software control of WDTPS)
#pragma config WDTE = SWDTEN    // WDT operating mode (WDT enabled/disabled by SWDTEN bit in WDTCON0)
#pragma config WDTCWS = WDTCWS_7// WDT Window Select bits (window always open (100%); software control; keyed access not required)
#pragma config WDTCCS = SC      // WDT input clock selector (Software Control)
#pragma config BBSIZE = BB512   // Boot Block Size Selection bits (512 words boot block size)
#pragma config BBEN = OFF       // Boot Block Enable bit (Boot Block disabled)
#pragma config SAFEN = OFF      // SAF Enable bit (SAF disabled)
#pragma config WRTAPP = OFF     // Application Block Write Protection bit (Application Block not write protected)
#pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot Block not write protected)
#pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration Register not write protected)
#pragma config WRTSAF = OFF     // Storage Area Flash Write Protection bit (SAF not write protected)
#pragma config LVP = OFF        // Low Voltage Programming Enable bit (High Voltage on MCLR/Vpp must be used for programming)
#pragma config CP = OFF         // UserNVM Program memory code protection bit (UserNVM code protection disabled)

#include <xc.h>

#define I2C_SLAVE_ADDR 0x00

void main(void) 
{
    WPUA   = 0b00111111;    // Enable all weak pull-up resistors on port A
    WPUB   = 0b11110000;    // Enable all weak pull-up resistors on port B
    WPUC   = 0b11111100;    // Enable all weak pull-up resistors on port C except
                            //    RC0 and RC1 to be used as I2C SCL and SDA
    TRISA  = 0b00110000;    // Set RA4 and RA5 as inputs
    ANSELA = 0b00110000;    // Set RA4 and RA5 to analog
    TRISB  = 0b00110000;    // Set RB6 and RB7 as inputs
    ANSELB = 0b11000000;    // Set RB6 and RB7 as analog
    TRISC  = 0b11111011;    // Set RC0, RC1, RC3, RC4, RC5, RC6, and RC7 as inputs
    ANSELC = 0b11111000;    // Set RC3, RC4, RC5, RC6, and RC7 as analog
#ifdef WRONG_WAY_TO_DO_PPS
    TX2CKPPS   = 0b01100;   // Use RB4 for TX2
    RX2DTPPS   = 0b01110;   // Use RB6 for RX2
    SSP1CLKPPS = 0b10000;   // Use RC0 as SCL
    SSP1DATPPS = 0b10001;   // Use RC1 as SDA
#else
    RB4PPS     = 0x11;      // Assign TX2 output  to RB4
    RX2DTPPS   = 0x0E;      // Assign RB6         to RX2 input
    RC0PPS     = 0x15;      // Assign SCL1 output to RC0
    SSP1CLKPPS = 0x10;      // Assign RC0         to SCL1 input
    RC1PPS     = 0x16;      // Assign SDA1 output to RC1
    SSP1DATPPS = 0x11;      // Assign RC1         to SDA1 input
#endif
    SSP1CON1 = 0b00100110;  // SSPEN enabled, WCOL no collision, SSPOV no overflow,
                            // CKP low hold, SSPM I2C slave 7-bit

    SSP1CON2 = 0b00000000;  // ACKSTAT received, RCEN disabled, RSEN disabled, 
                            // ACKEN disabled, ACKDT acknowledge, SEN disabled, 
                            // GCEN disabled, PEN disabled

    SSP1CON3 = 0b00000000;  // BOEN disabled, AHEN disabled, SBCDE disabled, 
                            // SDAHT 100 ns hold, ACKTIM ackseq, DHEN disabled, 
                            // PCIE disabled, SCIE disabled

    SSP1STAT = 0x00;
    SSP1BUF  = 0x00;
    SSP1MSK  = 0xff;
    SSP1ADD  = I2C_SLAVE_ADDR << 1;
    PIR3bits.SSP1IF = 0;    // Clear the SSP Interrupt flag
    PIE3bits.SSP1IE = 1;    // Enable SSP Interrupts
    INTCONbits.GIE = 1;     // Enable global interrupts
    INTCONbits.PEIE = 1;    // Enable peripheral interrupts
    /*
     * Embedded code never returns from main
     */
    for(;;)
    {

    }
}

PPS设置正确,但是我不知道I2C初始化代码是否正确。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM