Hi to everyone...
This had been a very long month for me, but at end the work is finished.
Thanks JimDon for your contribution, but the objective of work was to put MMIIC AP32 module to work, without using any additional code (If I should had used your code it would be a chief).
finally, the application note is right but not complete.
For all people who is interesting to configure an d use the module, here is the code I made and works whit two IIC devices (RTC DS1307 & EEPROM 24LC32A)
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
/* This function initializes MMIIC module of MCU */
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
void MMIIC_init (void)
{
MMCR1_MMEN =1; // Enable IIC
MMCR1_MMCLRBB =1; // Clear bus busy flag
MMCR1_MMTXAK =1; // MMIIC does not send acknowledge signal at 9th clock bit
MMCR2_MMRW =0; // R/W bit = 0
MMCR2_MMAST =0; // Slave mode actually
MMCR2_MMNAKIF =0;
MMCR2_MMALIF =0; // Clear flags
MMADR =MCU_ADDRESS; // Set specific slave address for MCU
MMSR =0; // Clear all flags (Status register)
// MMFDR: ?? =0; ?? =0; ?? =0; ?? =0; ?? =0; MBR2 =0; MMBR =0; MMBR =1;
MMFDR =1; // Set speed to 61,440kHz for Frequency Bus = 2457,6MHz (Divider by 40)
// SCL clock frequency MAX... RTC --> 100KHz EEPROM --> 400KHz
}
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
/* This function writes a 'data' in memory address 'data_addr' on 'device_addr'*/
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
void IIC_write_data (byte device_addr, byte data_addr, byte data)
{
MMCR2_MMRW =0; // Set Write mode
MMADR = device_addr; // set combined address of Slave for write
MMDTR = data_addr;
//------- Start of transmit bytes to IIC bus -----
MMCR2_MMAST = 1; // Start transfer - Master bit = 1
while (!MMSR_MMTXBE); // Wait till data transferred
while (MMSR_MMRXAK); // Wait for ACK from slave;
//------- Slave ACK occurred ------------
MMDTR = data; // Write data into device
while (!MMSR_MMTXBE); // Wait till data transferred
MMDTR = 0xFF; // Generate SCL impulse for slave to send ACK bit;
while (MMSR_MMRXAK); // Wait for ACK from slave
MMCR2_MMAST =0; // Slave mode actually
MMCR1_MMCLRBB =1; // Clear bus busy flag
MMADR =MCU_ADDRESS; // Set specific slave address for MCU
delay_ms(25);
}
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
/* This function reads a data in memory address 'data_addr' on 'device_addr', */
/* output from this function is byte "data" */
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
byte IIC_read_data (byte device_addr, byte data_addr)
{
byte data;
MMCR2_MMRW = 0; // Set Write mode
MMADR = device_addr; // Set combined address of Slave for write
MMDTR = data_addr; // Write data address into device
//------- Start of transmit bytes to IIC bus-----
MMCR2_MMAST = 1; // Start transfer - Master bit = 1
while (!MMSR_MMTXBE); // Wait till data transferred;
while (MMSR_MMRXAK); // Wait for ACK from slave;
//----- Slave ACK occurred------------
MMCR2_MMRW =1; // Set read operation
MMCR1_REPSEN =1; // Enable repeat Start bit
MMCR1_MMTXAK =0; // Master will generate ACK
//------ Start of transmit Repeat Start & "A1" to IIC bus-------
MMCR2_MMAST =1; // Start transfer - Master bit = 1
MMDTR = 0xFF; // Send repeated start and combined address
while (!(MMSR_MMTXBE)); // Wait till data transferred;
while (MMSR_MMRXAK); // Wait for ACK from slave;
//------ End of data reception -------
MMDTR = 0xFF; // Send SCL clocks for the slave to send data
MMCR1_MMTXAK = 1; // Disable master ACK after read byte from Slave
while (!MMSR_MMRXBF); // wait till data received;
data = MMDRR; // Read received data;
MMCR2_MMAST = 0; // Generate STOP bit - End of transfer;
MMCR1_MMCLRBB = 1; // Clear bus busy flag
MMADR =MCU_ADDRESS; // Set specific slave address for MCU
return data;
}
The red part was the missed part in application note. If the bus busy flag is not clear, the MCU never can generate STOP condition. The MCU address is a constant defined by programmer. In AP32 datasheet is recommended that after a routine of reading or writing program must update MCU slave own address (MCU_ADDRESS) if there is other master in the bus who wants to call the AP32 MCU.
You can make other functions to make a modular program as I did. You can make and start_function() that receives device address and memory address as input parameters; stop_function() that receives no parameters; IIC_write_data, IIC_write_many_data, IIC_read_data, IIC_read_many_data and so on...
Is an interesting module, so you can do many things... Just imagine.
Thanks,
Vladd, from Colombia (U. de Ant.)