无法让 I2C 与 PIC32MX270F256B 一起工作
Can't get I2C to work with PIC32MX270F256B
很抱歉打扰你们,但我已经花了好几个小时弄乱那个 PIC,我无法从 I2C1 端口获得任何东西!我想我一定是做错了什么,或者我忘了在配置位上打开某些东西,但我就是想不通是什么……
代码的目标是读取以 I2C 连接的实时时钟 (PCF8583)。我为 8 位 PIC18F45K50 编写了库并且工作正常,现在我想将它移到 PIC32MX。这是我在 PIC32 上的第一个项目。
这是我的配置(MCC 生成的):
#pragma config PMDL1WAY = ON // Peripheral Module Disable Configuration->Allow only one reconfiguration
#pragma config IOL1WAY = ON // Peripheral Pin Select Configuration->Allow only one reconfiguration
#pragma config FUSBIDIO = ON // USB USID Selection->Controlled by the USB Module
#pragma config FVBUSONIO = ON // USB VBUS ON Selection->Controlled by USB Module
// DEVCFG2
#pragma config FPLLIDIV = DIV_2 // PLL Input Divider->2x Divider
#pragma config FPLLMUL = MUL_20 // PLL Multiplier->20x Multiplier
#pragma config UPLLIDIV = DIV_12 // USB PLL Input Divider->12x Divider
#pragma config UPLLEN = OFF // USB PLL Enable->Disabled and Bypassed
#pragma config FPLLODIV = DIV_2 // System PLL Output Clock Divider->PLL Divide by 2
// DEVCFG1
#pragma config FNOSC = FRCPLL // Oscillator Selection Bits->Fast RC Osc with PLL
#pragma config FSOSCEN = ON // Secondary Oscillator Enable->Enabled
#pragma config IESO = ON // Internal/External Switch Over->Enabled
#pragma config POSCMOD = OFF // Primary Oscillator Configuration->Primary osc disabled
#pragma config OSCIOFNC = OFF // CLKO Output Signal Active on the OSCO Pin->Disabled
#pragma config FPBDIV = DIV_4 // Peripheral Clock Divisor->Pb_Clk is Sys_Clk/4
#pragma config FCKSM = CSDCMD // Clock Switching and Monitor Selection->Clock Switch Disable, FSCM Disabled
#pragma config WDTPS = PS1048576 // Watchdog Timer Postscaler->1:1048576
#pragma config WINDIS = OFF // Watchdog Timer Window Enable->Watchdog Timer is in Non-Window Mode
#pragma config FWDTEN = OFF // Watchdog Timer Enable->WDT Disabled (SWDTEN Bit Controls)
#pragma config FWDTWINSZ = WINSZ_25 // Watchdog Timer Window Size->Window Size is 25%
// DEVCFG0
#pragma config DEBUG = OFF // Background Debugger Enable->Debugger is Disabled
#pragma config JTAGEN = ON // JTAG Enable->JTAG Port Enabled
#pragma config ICESEL = ICS_PGx1 // ICE/ICD Comm Channel Select->Communicate on PGEC1/PGED1
#pragma config PWP = OFF // Program Flash Write Protect->Disable
#pragma config BWP = OFF // Boot Flash Write Protect bit->Protection Disabled
#pragma config CP = OFF // Code Protect->Protection Disabled
#include "mcc.h"
/**
@Summary
Indicates the exception cause.
@Description
This array identifies the cause for exception.
*/
static char *cause[] =
{
"Interrupt", "Undefined", "Undefined", "Undefined",
"Load/fetch address error", "Store address error",
"Instruction bus error", "Data bus error", "Syscall",
"Breakpoint", "Reserved instruction", "Coprocessor unusable",
"Arithmetic overflow", "Trap", "Reserved", "Reserved",
"Reserved", "Reserved", "Reserved"
};
void SYSTEM_Initialize(void)
{
PIN_MANAGER_Initialize();
OSCILLATOR_Initialize();
SPI1_Initialize();
I2C1_Initialize();
INTERRUPT_Initialize();
}
void SYSTEM_RegUnlock(void)
{
SYSKEY = 0x12345678;
SYSKEY = 0xAA996655;
SYSKEY = 0x556699AA;
}
void SYSTEM_RegLock(void)
{
SYSKEY = 0x00000000;
}
void OSCILLATOR_Initialize(void)
{
SYSTEM_RegUnlock();
// CF no clock failure; COSC FRCPLL; PLLODIV DIV_2; PBDIVRDY disabled; SLOCK out of lock; FRCDIV FRC/256; SLPEN Idle on WAIT instruction; NOSC FRCPLL; PLLMULT MUL_20; SOSCEN disabled; PBDIV DIV_4; CLKLOCK unlocked; OSWEN Switch is Complete; SOSCRDY disabled;
OSCCON = 0xF151100;
SYSTEM_RegLock();
// TUN Center Frequency;
OSCTUN = 0x0;
// DIVSWEN disabled; RSLP disabled; ACTIVE Active; ROSEL SYSCLK; OE Not Driven out on REFCLKO pin; SIDL disabled; RODIV 0; ON disabled;
REFOCON = 0x100;
// ROTRIM 0;
REFOTRIM = 0x0;
}
void _general_exception_handler ()
{
/* Mask off the ExcCode Field from the Cause Register
Refer to the MIPs Software User's manual */
uint8_t _excep_code;
uint8_t _excep_addr;
uint8_t *_cause_str;
_excep_code = (_CP0_GET_CAUSE() & 0x0000007C) >> 2;
_excep_addr = _CP0_GET_EPC();
_cause_str = cause[_excep_code];
while(1)
{
;
}
}
Main.c 在这里(简体):
#include "mcc_generated_files/mcc.h"
#include <stdio.h>
#include "Nokia5510.h"
#include "PCF8583.h"
int main(void)
{
// initialize the device
SYSTEM_Initialize();
while (1)
{
// Read values from PCF8583
unsigned char buf;
MasterStart();
MasterAddress(PCF8583_ADDRESS, 0); // WRITE
// Start writing at the PCF8583_100S_REG address
buf = PCF8583_100S_REG;
MasterWriteData(1, &buf);
MasterStart();
MasterAddress(PCF8583_ADDRESS, 1); // READ
MasterReadData(size, data);
MasterStop();
}
}
PCF8583 的功能在此处定义 PCF8583.c:
#include "PCF8583.h"
void myDelay()
{
int i;
for (i=0; i<1000; i++)
{
Nop();
}
}
void extractWeekday(char _data, char* str)
{
// Extract the 3 MSBs
_data = _data>>5;
if(_data == SUNDAY)
sprintf(str, "Sunday");
else if(_data == MONDAY)
sprintf(str, "Monday");
else if(_data == TUESDAY)
sprintf(str, "Tuesday");
else if(_data == WEDNESDAY)
sprintf(str, "Wednesday");
else if(_data == THURSDAY)
sprintf(str, "Thursday");
else if(_data == FRIDAY)
sprintf(str, "Friday");
else if(_data == SATURDAY)
sprintf(str, "Saturday");
}
void MasterStart()
{
I2C1CONbits.ON = 1;
// Generate a START condition by setting Start Enable bit
I2C1CONbits.SEN = 1;
// Wait for START to be completed
while(IFS1bits.I2C1MIF);
// Clear flag
IFS1bits.I2C1MIF = 0;
}
void MasterAddress(uint8_t _address, bool _RnW)
{
// Load the address + RW byte in SSP1BUF
// READ -> LSB=1 ; WRITE -> LSB=0
if (_RnW)
I2C1TRN = (_address<<1)+1;
else
I2C1TRN = _address<<1;
// Wait for ack
while (I2C1STATbits.ACKSTAT);
// Wait for MSSP interrupt
while (!IFS1bits.I2C1MIF);
// Clear flag
IFS1bits.I2C1MIF = 0;
}
void MasterWriteData(char _size, char* _data)
{
int i;
for (i=0; i<_size; i++)
{
// Load data in SSP1BUF
I2C1TRN = *(_data+i);
// Wait for ack
while (I2C1STATbits.ACKSTAT);
// Wait for MSSP interrupt
while (!IFS1bits.I2C1MIF);
// Clear flag
IFS1bits.I2C1MIF = 0;
}
}
void MasterReadData(char _size, char* _data)
{
int i;
for (i=0; i<size; i++)
{
// Enable reception
I2C1CONbits.RCEN = 1;
// Wait for MSSP interrupt flag and for the rx buffer to be full
while(!IFS1bits.I2C1MIF && !I2C1STATbits.RBF);
// Clear flag
IFS1bits.I2C1MIF = 0;
// Read the received byte
*(_data+i) = I2C1RCV;
// Clear BF to let MSSP know that we've read the buffer
I2C1STATbits.RBF = 0;
// Set ACK/NACK value to be sent slave
if (i != (size-1))
I2C1CONbits.ACKDT = 0; // ACK
else
I2C1CONbits.ACKDT = 1; // NACK for the last byte
// Initiate the ACK/NACK
I2C1CONbits.ACKEN = 1;
// Wait for ACK/NACK to be completed -> INT
while(!IFS1bits.I2C1MIF);
// Clear flag
IFS1bits.I2C1MIF = 0;
}
}
void MasterStop()
{
// Generate a STOP condition
I2C1CONbits.PEN = 1;
// Wait for STOP to be completed
while(!IFS1bits.I2C1MIF);
// Clear flag
IFS1bits.I2C1MIF = 0;
}
void PCF8583_init(char* _data)
{
*(_data) = CURRENT_100s;
*(_data+1) = CURRENT_SEC;
*(_data+2) = CURRENT_MIN;
*(_data+3) = CURRENT_HOURS;
*(_data+4) = CURRENT_DATE | (((CURRENT_YEAR-2016)%4)<<6);
*(_data+5) = CURRENT_MONTH | (CURRENT_WEEKDAY<<5);
*(_data+6) = CURRENT_TIMER;
// Start the counter
unsigned char buf;
MasterStart();
MasterAddress(PCF8583_ADDRESS, 0); // WRITE
// Register address in PCF8583
buf = PCF8583_CTRL_STATUS_REG;
MasterWriteData(1, &buf);
// Value PCF8583_START_COUNTING to make it start
buf = PCF8583_START_COUNTING;
MasterWriteData(1, &buf);
MasterStop();
myDelay();
// Set the date/month/time/...
MasterStart();
MasterAddress(PCF8583_ADDRESS, 0); // WRITE
// Start writing at the PCF8583_100S_REG address
buf = PCF8583_100S_REG;
MasterWriteData(1, &buf);
// Shove the datas in it
MasterWriteData(size, _data);
MasterStop();
myDelay();
}
以及对应的表头PCF8583.h:
#include "PCF8583.h"
void myDelay()
{
int i;
for (i=0; i<1000; i++)
{
Nop();
}
}
void extractWeekday(char _data, char* str)
{
// Extract the 3 MSBs
_data = _data>>5;
if(_data == SUNDAY)
sprintf(str, "Sunday");
else if(_data == MONDAY)
sprintf(str, "Monday");
else if(_data == TUESDAY)
sprintf(str, "Tuesday");
else if(_data == WEDNESDAY)
sprintf(str, "Wednesday");
else if(_data == THURSDAY)
sprintf(str, "Thursday");
else if(_data == FRIDAY)
sprintf(str, "Friday");
else if(_data == SATURDAY)
sprintf(str, "Saturday");
}
void MasterStart()
{
I2C1CONbits.ON = 1;
// Generate a START condition by setting Start Enable bit
I2C1CONbits.SEN = 1;
// Wait for START to be completed
while(IFS1bits.I2C1MIF);
// Clear flag
IFS1bits.I2C1MIF = 0;
}
void MasterAddress(uint8_t _address, bool _RnW)
{
// Load the address + RW byte in SSP1BUF
// READ -> LSB=1 ; WRITE -> LSB=0
if (_RnW)
I2C1TRN = (_address<<1)+1;
else
I2C1TRN = _address<<1;
// Wait for ack
while (I2C1STATbits.ACKSTAT);
// Wait for MSSP interrupt
while (!IFS1bits.I2C1MIF);
// Clear flag
IFS1bits.I2C1MIF = 0;
}
void MasterWriteData(char _size, char* _data)
{
int i;
for (i=0; i<_size; i++)
{
// Load data in SSP1BUF
I2C1TRN = *(_data+i);
// Wait for ack
while (I2C1STATbits.ACKSTAT);
// Wait for MSSP interrupt
while (!IFS1bits.I2C1MIF);
// Clear flag
IFS1bits.I2C1MIF = 0;
}
}
void MasterReadData(char _size, char* _data)
{
int i;
for (i=0; i<size; i++)
{
// Enable reception
I2C1CONbits.RCEN = 1;
// Wait for MSSP interrupt flag and for the rx buffer to be full
while(!IFS1bits.I2C1MIF && !I2C1STATbits.RBF);
// Clear flag
IFS1bits.I2C1MIF = 0;
// Read the received byte
*(_data+i) = I2C1RCV;
// Clear BF to let MSSP know that we've read the buffer
I2C1STATbits.RBF = 0;
// Set ACK/NACK value to be sent slave
if (i != (size-1))
I2C1CONbits.ACKDT = 0; // ACK
else
I2C1CONbits.ACKDT = 1; // NACK for the last byte
// Initiate the ACK/NACK
I2C1CONbits.ACKEN = 1;
// Wait for ACK/NACK to be completed -> INT
while(!IFS1bits.I2C1MIF);
// Clear flag
IFS1bits.I2C1MIF = 0;
}
}
void MasterStop()
{
// Generate a STOP condition
I2C1CONbits.PEN = 1;
// Wait for STOP to be completed
while(!IFS1bits.I2C1MIF);
// Clear flag
IFS1bits.I2C1MIF = 0;
}
void PCF8583_init(char* _data)
{
*(_data) = CURRENT_100s;
*(_data+1) = CURRENT_SEC;
*(_data+2) = CURRENT_MIN;
*(_data+3) = CURRENT_HOURS;
*(_data+4) = CURRENT_DATE | (((CURRENT_YEAR-2016)%4)<<6);
*(_data+5) = CURRENT_MONTH | (CURRENT_WEEKDAY<<5);
*(_data+6) = CURRENT_TIMER;
// Start the counter
unsigned char buf;
MasterStart();
MasterAddress(PCF8583_ADDRESS, 0); // WRITE
// Register address in PCF8583
buf = PCF8583_CTRL_STATUS_REG;
MasterWriteData(1, &buf);
// Value PCF8583_START_COUNTING to make it start
buf = PCF8583_START_COUNTING;
MasterWriteData(1, &buf);
MasterStop();
myDelay();
// Set the date/month/time/...
MasterStart();
MasterAddress(PCF8583_ADDRESS, 0); // WRITE
// Start writing at the PCF8583_100S_REG address
buf = PCF8583_100S_REG;
MasterWriteData(1, &buf);
// Shove the datas in it
MasterWriteData(size, _data);
MasterStop();
myDelay();
}
结果是:SCL1/SDA1 上什么也没有发生!我添加了一些 2k 上拉并使用逻辑分析仪对其进行监控。我启动逻辑分析仪,然后启动电路,以便能够监控 PIC 在启动时正在做什么。
任何帮助或线索将不胜感激!
提前致谢!
此致。
埃里克
在配置位中启用 JTAG 是否有原因?如果您使用的是常规 PICKIT3 等,那么您可能不需要打开 JTAG。也,我看起来并不难,但是你关闭了模拟引脚功能吗?
这两点都会让 Digital IO 从一开始就无法正常工作。
AD1PCFGbits.PCFG = 0xFFFF;
很抱歉打扰你们,但我已经花了好几个小时弄乱那个 PIC,我无法从 I2C1 端口获得任何东西!我想我一定是做错了什么,或者我忘了在配置位上打开某些东西,但我就是想不通是什么……
代码的目标是读取以 I2C 连接的实时时钟 (PCF8583)。我为 8 位 PIC18F45K50 编写了库并且工作正常,现在我想将它移到 PIC32MX。这是我在 PIC32 上的第一个项目。
这是我的配置(MCC 生成的):
#pragma config PMDL1WAY = ON // Peripheral Module Disable Configuration->Allow only one reconfiguration
#pragma config IOL1WAY = ON // Peripheral Pin Select Configuration->Allow only one reconfiguration
#pragma config FUSBIDIO = ON // USB USID Selection->Controlled by the USB Module
#pragma config FVBUSONIO = ON // USB VBUS ON Selection->Controlled by USB Module
// DEVCFG2
#pragma config FPLLIDIV = DIV_2 // PLL Input Divider->2x Divider
#pragma config FPLLMUL = MUL_20 // PLL Multiplier->20x Multiplier
#pragma config UPLLIDIV = DIV_12 // USB PLL Input Divider->12x Divider
#pragma config UPLLEN = OFF // USB PLL Enable->Disabled and Bypassed
#pragma config FPLLODIV = DIV_2 // System PLL Output Clock Divider->PLL Divide by 2
// DEVCFG1
#pragma config FNOSC = FRCPLL // Oscillator Selection Bits->Fast RC Osc with PLL
#pragma config FSOSCEN = ON // Secondary Oscillator Enable->Enabled
#pragma config IESO = ON // Internal/External Switch Over->Enabled
#pragma config POSCMOD = OFF // Primary Oscillator Configuration->Primary osc disabled
#pragma config OSCIOFNC = OFF // CLKO Output Signal Active on the OSCO Pin->Disabled
#pragma config FPBDIV = DIV_4 // Peripheral Clock Divisor->Pb_Clk is Sys_Clk/4
#pragma config FCKSM = CSDCMD // Clock Switching and Monitor Selection->Clock Switch Disable, FSCM Disabled
#pragma config WDTPS = PS1048576 // Watchdog Timer Postscaler->1:1048576
#pragma config WINDIS = OFF // Watchdog Timer Window Enable->Watchdog Timer is in Non-Window Mode
#pragma config FWDTEN = OFF // Watchdog Timer Enable->WDT Disabled (SWDTEN Bit Controls)
#pragma config FWDTWINSZ = WINSZ_25 // Watchdog Timer Window Size->Window Size is 25%
// DEVCFG0
#pragma config DEBUG = OFF // Background Debugger Enable->Debugger is Disabled
#pragma config JTAGEN = ON // JTAG Enable->JTAG Port Enabled
#pragma config ICESEL = ICS_PGx1 // ICE/ICD Comm Channel Select->Communicate on PGEC1/PGED1
#pragma config PWP = OFF // Program Flash Write Protect->Disable
#pragma config BWP = OFF // Boot Flash Write Protect bit->Protection Disabled
#pragma config CP = OFF // Code Protect->Protection Disabled
#include "mcc.h"
/**
@Summary
Indicates the exception cause.
@Description
This array identifies the cause for exception.
*/
static char *cause[] =
{
"Interrupt", "Undefined", "Undefined", "Undefined",
"Load/fetch address error", "Store address error",
"Instruction bus error", "Data bus error", "Syscall",
"Breakpoint", "Reserved instruction", "Coprocessor unusable",
"Arithmetic overflow", "Trap", "Reserved", "Reserved",
"Reserved", "Reserved", "Reserved"
};
void SYSTEM_Initialize(void)
{
PIN_MANAGER_Initialize();
OSCILLATOR_Initialize();
SPI1_Initialize();
I2C1_Initialize();
INTERRUPT_Initialize();
}
void SYSTEM_RegUnlock(void)
{
SYSKEY = 0x12345678;
SYSKEY = 0xAA996655;
SYSKEY = 0x556699AA;
}
void SYSTEM_RegLock(void)
{
SYSKEY = 0x00000000;
}
void OSCILLATOR_Initialize(void)
{
SYSTEM_RegUnlock();
// CF no clock failure; COSC FRCPLL; PLLODIV DIV_2; PBDIVRDY disabled; SLOCK out of lock; FRCDIV FRC/256; SLPEN Idle on WAIT instruction; NOSC FRCPLL; PLLMULT MUL_20; SOSCEN disabled; PBDIV DIV_4; CLKLOCK unlocked; OSWEN Switch is Complete; SOSCRDY disabled;
OSCCON = 0xF151100;
SYSTEM_RegLock();
// TUN Center Frequency;
OSCTUN = 0x0;
// DIVSWEN disabled; RSLP disabled; ACTIVE Active; ROSEL SYSCLK; OE Not Driven out on REFCLKO pin; SIDL disabled; RODIV 0; ON disabled;
REFOCON = 0x100;
// ROTRIM 0;
REFOTRIM = 0x0;
}
void _general_exception_handler ()
{
/* Mask off the ExcCode Field from the Cause Register
Refer to the MIPs Software User's manual */
uint8_t _excep_code;
uint8_t _excep_addr;
uint8_t *_cause_str;
_excep_code = (_CP0_GET_CAUSE() & 0x0000007C) >> 2;
_excep_addr = _CP0_GET_EPC();
_cause_str = cause[_excep_code];
while(1)
{
;
}
}
Main.c 在这里(简体):
#include "mcc_generated_files/mcc.h"
#include <stdio.h>
#include "Nokia5510.h"
#include "PCF8583.h"
int main(void)
{
// initialize the device
SYSTEM_Initialize();
while (1)
{
// Read values from PCF8583
unsigned char buf;
MasterStart();
MasterAddress(PCF8583_ADDRESS, 0); // WRITE
// Start writing at the PCF8583_100S_REG address
buf = PCF8583_100S_REG;
MasterWriteData(1, &buf);
MasterStart();
MasterAddress(PCF8583_ADDRESS, 1); // READ
MasterReadData(size, data);
MasterStop();
}
}
PCF8583 的功能在此处定义 PCF8583.c:
#include "PCF8583.h"
void myDelay()
{
int i;
for (i=0; i<1000; i++)
{
Nop();
}
}
void extractWeekday(char _data, char* str)
{
// Extract the 3 MSBs
_data = _data>>5;
if(_data == SUNDAY)
sprintf(str, "Sunday");
else if(_data == MONDAY)
sprintf(str, "Monday");
else if(_data == TUESDAY)
sprintf(str, "Tuesday");
else if(_data == WEDNESDAY)
sprintf(str, "Wednesday");
else if(_data == THURSDAY)
sprintf(str, "Thursday");
else if(_data == FRIDAY)
sprintf(str, "Friday");
else if(_data == SATURDAY)
sprintf(str, "Saturday");
}
void MasterStart()
{
I2C1CONbits.ON = 1;
// Generate a START condition by setting Start Enable bit
I2C1CONbits.SEN = 1;
// Wait for START to be completed
while(IFS1bits.I2C1MIF);
// Clear flag
IFS1bits.I2C1MIF = 0;
}
void MasterAddress(uint8_t _address, bool _RnW)
{
// Load the address + RW byte in SSP1BUF
// READ -> LSB=1 ; WRITE -> LSB=0
if (_RnW)
I2C1TRN = (_address<<1)+1;
else
I2C1TRN = _address<<1;
// Wait for ack
while (I2C1STATbits.ACKSTAT);
// Wait for MSSP interrupt
while (!IFS1bits.I2C1MIF);
// Clear flag
IFS1bits.I2C1MIF = 0;
}
void MasterWriteData(char _size, char* _data)
{
int i;
for (i=0; i<_size; i++)
{
// Load data in SSP1BUF
I2C1TRN = *(_data+i);
// Wait for ack
while (I2C1STATbits.ACKSTAT);
// Wait for MSSP interrupt
while (!IFS1bits.I2C1MIF);
// Clear flag
IFS1bits.I2C1MIF = 0;
}
}
void MasterReadData(char _size, char* _data)
{
int i;
for (i=0; i<size; i++)
{
// Enable reception
I2C1CONbits.RCEN = 1;
// Wait for MSSP interrupt flag and for the rx buffer to be full
while(!IFS1bits.I2C1MIF && !I2C1STATbits.RBF);
// Clear flag
IFS1bits.I2C1MIF = 0;
// Read the received byte
*(_data+i) = I2C1RCV;
// Clear BF to let MSSP know that we've read the buffer
I2C1STATbits.RBF = 0;
// Set ACK/NACK value to be sent slave
if (i != (size-1))
I2C1CONbits.ACKDT = 0; // ACK
else
I2C1CONbits.ACKDT = 1; // NACK for the last byte
// Initiate the ACK/NACK
I2C1CONbits.ACKEN = 1;
// Wait for ACK/NACK to be completed -> INT
while(!IFS1bits.I2C1MIF);
// Clear flag
IFS1bits.I2C1MIF = 0;
}
}
void MasterStop()
{
// Generate a STOP condition
I2C1CONbits.PEN = 1;
// Wait for STOP to be completed
while(!IFS1bits.I2C1MIF);
// Clear flag
IFS1bits.I2C1MIF = 0;
}
void PCF8583_init(char* _data)
{
*(_data) = CURRENT_100s;
*(_data+1) = CURRENT_SEC;
*(_data+2) = CURRENT_MIN;
*(_data+3) = CURRENT_HOURS;
*(_data+4) = CURRENT_DATE | (((CURRENT_YEAR-2016)%4)<<6);
*(_data+5) = CURRENT_MONTH | (CURRENT_WEEKDAY<<5);
*(_data+6) = CURRENT_TIMER;
// Start the counter
unsigned char buf;
MasterStart();
MasterAddress(PCF8583_ADDRESS, 0); // WRITE
// Register address in PCF8583
buf = PCF8583_CTRL_STATUS_REG;
MasterWriteData(1, &buf);
// Value PCF8583_START_COUNTING to make it start
buf = PCF8583_START_COUNTING;
MasterWriteData(1, &buf);
MasterStop();
myDelay();
// Set the date/month/time/...
MasterStart();
MasterAddress(PCF8583_ADDRESS, 0); // WRITE
// Start writing at the PCF8583_100S_REG address
buf = PCF8583_100S_REG;
MasterWriteData(1, &buf);
// Shove the datas in it
MasterWriteData(size, _data);
MasterStop();
myDelay();
}
以及对应的表头PCF8583.h:
#include "PCF8583.h"
void myDelay()
{
int i;
for (i=0; i<1000; i++)
{
Nop();
}
}
void extractWeekday(char _data, char* str)
{
// Extract the 3 MSBs
_data = _data>>5;
if(_data == SUNDAY)
sprintf(str, "Sunday");
else if(_data == MONDAY)
sprintf(str, "Monday");
else if(_data == TUESDAY)
sprintf(str, "Tuesday");
else if(_data == WEDNESDAY)
sprintf(str, "Wednesday");
else if(_data == THURSDAY)
sprintf(str, "Thursday");
else if(_data == FRIDAY)
sprintf(str, "Friday");
else if(_data == SATURDAY)
sprintf(str, "Saturday");
}
void MasterStart()
{
I2C1CONbits.ON = 1;
// Generate a START condition by setting Start Enable bit
I2C1CONbits.SEN = 1;
// Wait for START to be completed
while(IFS1bits.I2C1MIF);
// Clear flag
IFS1bits.I2C1MIF = 0;
}
void MasterAddress(uint8_t _address, bool _RnW)
{
// Load the address + RW byte in SSP1BUF
// READ -> LSB=1 ; WRITE -> LSB=0
if (_RnW)
I2C1TRN = (_address<<1)+1;
else
I2C1TRN = _address<<1;
// Wait for ack
while (I2C1STATbits.ACKSTAT);
// Wait for MSSP interrupt
while (!IFS1bits.I2C1MIF);
// Clear flag
IFS1bits.I2C1MIF = 0;
}
void MasterWriteData(char _size, char* _data)
{
int i;
for (i=0; i<_size; i++)
{
// Load data in SSP1BUF
I2C1TRN = *(_data+i);
// Wait for ack
while (I2C1STATbits.ACKSTAT);
// Wait for MSSP interrupt
while (!IFS1bits.I2C1MIF);
// Clear flag
IFS1bits.I2C1MIF = 0;
}
}
void MasterReadData(char _size, char* _data)
{
int i;
for (i=0; i<size; i++)
{
// Enable reception
I2C1CONbits.RCEN = 1;
// Wait for MSSP interrupt flag and for the rx buffer to be full
while(!IFS1bits.I2C1MIF && !I2C1STATbits.RBF);
// Clear flag
IFS1bits.I2C1MIF = 0;
// Read the received byte
*(_data+i) = I2C1RCV;
// Clear BF to let MSSP know that we've read the buffer
I2C1STATbits.RBF = 0;
// Set ACK/NACK value to be sent slave
if (i != (size-1))
I2C1CONbits.ACKDT = 0; // ACK
else
I2C1CONbits.ACKDT = 1; // NACK for the last byte
// Initiate the ACK/NACK
I2C1CONbits.ACKEN = 1;
// Wait for ACK/NACK to be completed -> INT
while(!IFS1bits.I2C1MIF);
// Clear flag
IFS1bits.I2C1MIF = 0;
}
}
void MasterStop()
{
// Generate a STOP condition
I2C1CONbits.PEN = 1;
// Wait for STOP to be completed
while(!IFS1bits.I2C1MIF);
// Clear flag
IFS1bits.I2C1MIF = 0;
}
void PCF8583_init(char* _data)
{
*(_data) = CURRENT_100s;
*(_data+1) = CURRENT_SEC;
*(_data+2) = CURRENT_MIN;
*(_data+3) = CURRENT_HOURS;
*(_data+4) = CURRENT_DATE | (((CURRENT_YEAR-2016)%4)<<6);
*(_data+5) = CURRENT_MONTH | (CURRENT_WEEKDAY<<5);
*(_data+6) = CURRENT_TIMER;
// Start the counter
unsigned char buf;
MasterStart();
MasterAddress(PCF8583_ADDRESS, 0); // WRITE
// Register address in PCF8583
buf = PCF8583_CTRL_STATUS_REG;
MasterWriteData(1, &buf);
// Value PCF8583_START_COUNTING to make it start
buf = PCF8583_START_COUNTING;
MasterWriteData(1, &buf);
MasterStop();
myDelay();
// Set the date/month/time/...
MasterStart();
MasterAddress(PCF8583_ADDRESS, 0); // WRITE
// Start writing at the PCF8583_100S_REG address
buf = PCF8583_100S_REG;
MasterWriteData(1, &buf);
// Shove the datas in it
MasterWriteData(size, _data);
MasterStop();
myDelay();
}
结果是:SCL1/SDA1 上什么也没有发生!我添加了一些 2k 上拉并使用逻辑分析仪对其进行监控。我启动逻辑分析仪,然后启动电路,以便能够监控 PIC 在启动时正在做什么。
任何帮助或线索将不胜感激!
提前致谢!
此致。
埃里克
在配置位中启用 JTAG 是否有原因?如果您使用的是常规 PICKIT3 等,那么您可能不需要打开 JTAG。也,我看起来并不难,但是你关闭了模拟引脚功能吗? 这两点都会让 Digital IO 从一开始就无法正常工作。
AD1PCFGbits.PCFG = 0xFFFF;