Hi, I've recently bought Tiva C TM4C1294XL board and I'm playing with it. Previously, I've worked with 8051 microcontroller and used PCF8591 DAC/ADC peripheral with it. Now I’d like to use it with Tiva and I ran into some problems. I’ve been googling for the past two weeks and couldn’t find any solution, so I’m hoping someone here has some experience with it, or can help.
Problem is that my PCF8591 acts like it’s not even connected to I2C bus, I can’t find it while scanning the bus, nor can I communicate with it.
On the other hand, if you look at the code, you’ll see that I’m also using DS1631 temperature sensor, connected to the same I2C0 bus with address 0x90, and it works perfect, I’m able to communicate with it and get temperature readings. It is also the only device I see when performing I2C Bus scan.
PCF8591 datasheet - http://www.nxp.com/documents/data_sheet/PCF8591.pdf
#include <stdbool.h> #include <stdint.h> #include "inc/hw_i2c.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "driverlib/gpio.h" #include "driverlib/i2c.h" #include "driverlib/interrupt.h" #include "driverlib/pin_map.h" #include "driverlib/sysctl.h" #include "driverlib/uart.h" #include "utils/uartstdio.h" #include "driverlib/rom_map.h" #include "inc/hw_types.h" #include "inc/hw_gpio.h" uint32_t ui32SysClock; volatile uint8_t data[10]; const uint8_t DS1631address = 0x90; const uint8_t DACaddress = 0x9E; const bool DebuggingMode = true; void InitConsole(void) { SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); GPIOPinConfigure(GPIO_PA0_U0RX); GPIOPinConfigure(GPIO_PA1_U0TX); SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0); UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC); GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1); UARTStdioConfig(0, 115200, 16000000); } void ftoa(float f,char *buf) { /*Function acquired from forum: * http://e2e.ti.com/support/microcontrollers/stellaris_arm/f/471/p/44193/156824.aspx */ int pos=0,ix,dp,num; if (f<0) { buf[pos++]='-'; f = -f; } dp=0; while (f>=10.0) { f=f/10.0; dp++; } for (ix=1;ix<8;ix++) { num = (int)f; f=f-num; if (num>9) buf[pos++]='#'; else buf[pos++]='0'+num; if (dp==0) buf[pos++]='.'; f=f*10.0; dp--; } } void i2c0_init() { MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0); MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); MAP_GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3); MAP_GPIOPinConfigure(GPIO_PB3_I2C0SDA); MAP_GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2); MAP_GPIOPinConfigure(GPIO_PB2_I2C0SCL); I2CMasterInitExpClk(I2C0_BASE, SysCtlClockGet(), false); while (I2CMasterBusy(I2C0_BASE)); if (DebuggingMode) UARTprintf("\n Initializing I2C0 -> Error: %u ",I2CMasterErr(I2C0_BASE)); } uint32_t i2c0_write(uint8_t addr, uint8_t value) { uint32_t error = { 0 }; I2CMasterSlaveAddrSet(I2C0_BASE, addr>>1, false); while (I2CMasterBusy(I2C0_BASE)); I2CMasterDataPut(I2C0_BASE, value); while (I2CMasterBusy(I2C0_BASE)); I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_SEND); while (I2CMasterBusy(I2C0_BASE)); if (DebuggingMode) UARTprintf("\n Sending data(%X) -> Error: %u ",value, I2CMasterErr(I2C0_BASE)); return I2CMasterErr(I2C0_BASE); } void i2c0_read(uint8_t addr, uint8_t *RxData, uint8_t N) { uint8_t i; I2CMasterSlaveAddrSet(I2C0_BASE, addr>>1, true); while (I2CMasterBusy(I2C0_BASE)); if (N==1) { I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE); while (I2CMasterBusy(I2C0_BASE)); RxData[0]=I2CMasterDataGet(I2C0_BASE); while (I2CMasterBusy(I2C0_BASE)); if (DebuggingMode) UARTprintf("\n Reading data(%X) -> Error: %u ",RxData[0], I2CMasterErr(I2C0_BASE)); } else { I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START); while (I2CMasterBusy(I2C0_BASE)); RxData[0]=I2CMasterDataGet(I2C0_BASE); while (I2CMasterBusy(I2C0_BASE)); if (DebuggingMode) UARTprintf("\n Reading data(%X) -> Error: %u ",RxData[0], I2CMasterErr(I2C0_BASE)); for (i=1;i<(N-1);i++) { I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_CONT); while (I2CMasterBusy(I2C0_BASE)); RxData[i]=I2CMasterDataGet(I2C0_BASE); while (I2CMasterBusy(I2C0_BASE)); if (DebuggingMode) UARTprintf("\n Reading data(%X) -> Error: %u ",RxData[i], I2CMasterErr(I2C0_BASE)); } I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH); while (I2CMasterBusy(I2C0_BASE)); RxData[N-1]=I2CMasterDataGet(I2C0_BASE); while (I2CMasterBusy(I2C0_BASE)); if (DebuggingMode) UARTprintf("\n Reading data(%X) -> Error: %u ",RxData[N-1], I2CMasterErr(I2C0_BASE)); } } void DS1631_init() { i2c0_write(DS1631address,DS1631address); i2c0_write(DS1631address,0xAC); i2c0_write(DS1631address,0x0C); i2c0_write(DS1631address,DS1631address); i2c0_write(DS1631address,0x51); } float get_temperature() { uint8_t Rx[2]; float temperature; i2c0_write(DS1631address,DS1631address); i2c0_write(DS1631address,0xAA); i2c0_read(DS1631address,Rx,2); temperature=Rx[0]+((Rx[1]&0x80) ? 0.5:0); return temperature; } uint8_t read_ain(uint8_t channel) { uint8_t Rx[2]; if (channel > 3) channel=3; i2c0_write(DACaddress,DACaddress); i2c0_write(DACaddress,0x40+channel); i2c0_read(DACaddress,Rx,2); return Rx[1]; } void set_dac(uint8_t value) { i2c0_write(DACaddress,DACaddress); i2c0_write(DACaddress,0x40); i2c0_write(DACaddress,value); } int main(void) { ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000); MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION); MAP_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE,GPIO_PIN_0 | GPIO_PIN_1); GPIOPinWrite(GPIO_PORTN_BASE,GPIO_PIN_0,0); GPIOPinWrite(GPIO_PORTN_BASE,GPIO_PIN_1,0); InitConsole(); i2c0_init(); DS1631_init(); uint8_t ain=read_ain(0); char myTemp[6]; ftoa(get_temperature(),myTemp); UARTprintf("\n Got temperature: %s ",myTemp); UARTprintf("\n Reading channel 1: %u",ain); set_dac(150); GPIOPinWrite(GPIO_PORTN_BASE,GPIO_PIN_1,0xFF); UARTprintf("\n Done!...\n"); while(1); }
Lastly, this is a working part of code from 8051 with which DAC/ADC module works fine:
#define PCF8591_adr 0x9E int read_ain(unsigned char channel) { int ad_byte; if(channel > 3) channel = 3; i2c_start(); i2c_write(PCF8591_adr); i2c_write(0x40+channel); i2c_start(); i2c_write(PCF8591_adr+1); ad_byte = i2c_read(ACK); ad_byte = i2c_read(NACK); i2c_stop(); return ad_byte; } void set_dac(unsigned char value) { i2c_start();
i2c_write(PCF8591_adr);
i2c_write(0x40);
i2c_write(value);
i2c_stop(); }
Thanks for your time.