// Reads from a device using I2C. The command character is written first and then len bytes are read from the device. void ReadI2C(char slaveAddress, char cmd, int len, char *data) { I2CHW_bWriteBytes(slaveAddress, &cmd, 1, I2CHW_NoStop); // Write cmd byte while (!(I2CHW_bReadI2CStatus() & I2CHW_WR_COMPLETE)); // Wait until ACK is received I2CHW_ClrWrStatus(); // Clear write bit I2CHW_fReadBytes(slaveAddress, data, len, I2CHW_CompleteXfer); // Read len bytes into data while (!(I2CHW_bReadI2CStatus() & I2CHW_RD_COMPLETE)); // Wait until reading is done I2CHW_ClrRdStatus(); // Clear read bit }
void main(void){ M8C_EnableGInt; M8C_EnableIntMask(INT_MSK0, INT_MSK0_GPIO); I2CHW_Start(); I2CHW_EnableSlave(); I2CHW_EnableInt(); AMUX4_Start(); PGA_1_Start(PGA_1_HIGHPOWER); ADCINC_Start(ADCINC_HIGHPOWER); TX8_Start(TX8_PARITY_NONE); LED_DBG_ON(); TX8_CPutString("I2C slave addr:0x"); TX8_PutSHexByte(I2CHW_SLAVE_ADDR); TX8_PutCRLF(); LED_DBG_OFF(); for(;;){ // I2C i2c_status = I2CHW_bReadI2CStatus(); if(i2c_status & I2CHW_WR_COMPLETE){ // master->slave I2CHW_ClrWrStatus(); I2CHW_InitWrite(buf_rx, BUF_SIZE); } if(i2c_status & I2CHW_RD_COMPLETE){ // slave->master I2CHW_ClrRdStatus(); I2CHW_InitRamRead(buf_tx, BUF_SIZE); } // ADC for(ad_pin = 0; ad_pin < 4; ad_pin++){ ad = get_adc(ad_pin); weights[ad_pin] = ad; TX8_PutChar(ad_pin+'0'); TX8_CPutString(":"); TX8_PutString(intToStr(ad,buf)); TX8_PutCRLF(); } buf_tx[0] = 'a'; buf_tx[1] = 'b'; buf_tx[2] = 'c'; buf_tx[3] = 'd'; } }
// Writes a command to a device using I2C. The command character is sent first followed by len bytes. Limited to 31 bytes. Use the other // I2C function to send more bytes. Characters to be sent should be placed after the len parameter void WriteI2C(char slaveAddress, char cmd, int len, ...) { char buf[32]; // Buffer that will contain the data t be sent int i; va_list v1; buf[0] = cmd; // First byte is the cmd character va_start(v1, len); // Variadic arguments are used to easily send bytes to a I2C device. for (i = 0; i < len; i++) // Get len arguments from the function buf[i + 1] = va_arg(v1, char); // Put argument in buf shifted by one va_end(v1); I2CHW_bWriteBytes(slaveAddress, buf, len + 1, I2CHW_CompleteXfer); // Write len+1 bytes from buf while (!(I2CHW_bReadI2CStatus() & I2CHW_WR_COMPLETE)); // Wait until ACK is received I2CHW_ClrWrStatus(); // Clear write bit }
void main(void) { M8C_EnableGInt ; // Uncomment this line to enable Global Interrupts // Start the UART(with no parity), and Counter16 UART_Start(UART_PARITY_NONE); // clock for moving serial Counter16_Start(); // Start I2CHW I2CHW_Start(); I2CHW_EnableMstr(); I2CHW_EnableInt(); // This is the command usage string UART_CPutString("########################## I2C External SRAM ########################\r\n\ # W # XX T [Data]\r\n\ # W - Write command\r\n\ # # - Group Address (0 - 7)\r\n\ # XX - Memory Location in hex (00 - FF)\r\n\ # T - Data Type, either A for ASCII or H for Hexadecimal\r\n\ # Data - Either ASCII string or Hexadecimal separates by spaces\r\n\ #\t\t\tA - Mary had a little lamb\r\n\ #\t\t\tH - 01 FF A0 0F D8 C3\r\n\ #\r\n\ # R # XX T NN\r\n\ # R - Read command\r\n\ # # - Group Address (0 - 7)\r\n\ # XX - Memory Location in hex (00 - FF)\r\n\ # T - Data Type, either A for ASCII or H for Hexadecimal\r\n\ # NN - Number of bytes to read in hexadecimal\r\n\ #####################################################################\r\n"); while (1) { char *cmd; char *params; char slaveAddress = 0x50; // 010100000 R/W shifted to front GetLine(buf, 79); // Retrieves a line with a maximum length of 70 characters and put it in buf. memset(data, 0x00, 256); // Initialize all the set {data} to NULL bytes cmd = Lowercase(cstrtok(buf, " ")); // Get the first word from the entered string and lowercase it. if (strlen(cmd) == 1 && cmd[0] == 'w') // If the command is one letter and it is w, then write command { int groupAddress; // only 1 and 2 actually go to SRAM int memLoc; char dataType; int len; params = cstrtok(0x00, " "); // 0x00 indicates it will continue from last cstrtok command and get next word. This gets the next parameter // csscanf if used to parse the string into values such as hexadecimal or integers // It returns the number of parameters it parsed which should be one // If the length of the params is not right or it does not parse the right amount, it returns an error // %d gets an integer, this is the groupAddress if (strlen(params) != 1 || csscanf(params, "%d", &groupAddress) != 1) goto error; // %x gets a hexadecimal value, this can read capital or lowercase letters, this is the memory location params = cstrtok(0x00, " "); if (strlen(params) != 2 || csscanf(params, "%x", &memLoc) != 1) goto error; // %c gets a character, the data type character params = cstrtok(0x00, " "); if (strlen(params) != 1 || csscanf(params, "%c", &dataType) != 1) goto error; // This reads the rest of the string and stores it in params. // If the length is zero or if cstrtok returns 0, this means that there was no valid string/hex entered params = cstrtok(0x00, "\0"); if (strlen(params) == 0 || params == 0x00) goto error; // They did all the params but didn't write anything dataType = tolower(dataType); // Lowercase the data type if (groupAddress < 0 || groupAddress > 7) goto error; // groupAddress was not in range data[0] = memLoc; // First byte needs to be the memory location according to PCF8570 datasheet slaveAddress |= groupAddress; // ORs the group 2 address to the group 1 address to get slaveAddress if (dataType == 'a') // If the data type is ASCII { strcpy((data + 1), params); // Copy the string from params and put it right after the data[0] byte len = strlen((data + 1)) + 1; // len is the number of bytes to write, it is the length of the string and then +1 because of the memLoc byte // Cant just do strlen(data) because data[0] could be 0x00 and it would return 0 as the string length } else if (dataType == 'h') // If the data type is hex { // Take ASCII encoded hex data params and put it after data[0], returns number of bytes converted if ((len = HexConversion(params, (data + 1))) == -1) goto error; len++; // Add one to the length because of the memLoc byte at data[0] } else goto error; I2CHW_bWriteBytes(slaveAddress, data, len, I2CHW_CompleteXfer); // Write len bytes from data while (!(I2CHW_bReadI2CStatus() & I2CHW_WR_COMPLETE)); // Wait while it is writing I2CHW_ClrWrStatus(); // Clear the write bit csprintf(data, "%x bytes were written", len); // csprintf takes the string and substitutes %x for len, puts into data str UART_PutString(data); // Print the string to UART UART_PutCRLF(); } else if (strlen(cmd) == 1 && cmd[0] == 'r') // If the command is one letter and it is r, then read command { int groupAddress; int memLoc; char dataType; int numBytes; char hexStr[4]; int i; // csscanf if used to parse the string into values such as hexadecimal or integers // It returns the number of parameters it parsed which should be one // If the length of the params is not right or it does not parse the right amount, it returns an error // %d gets an integer, this is the groupAddress params = cstrtok(0x00, " "); if (strlen(params) != 1 || csscanf(params, "%d", &groupAddress) != 1) goto error; // %x gets a hexadecimal value, this can read capital or lowercase letters, this is the memory location params = cstrtok(0x00, " "); if (strlen(params) != 2 || csscanf(params, "%x", &memLoc) != 1) goto error; // %c gets a character, the data type character params = cstrtok(0x00, " "); if (strlen(params) != 1 || csscanf(params, "%c", &dataType) != 1) goto error; // %x gets a hexadecimal value, number of bytes to read params = cstrtok(0x00, " "); if (strlen(params) != 2 || csscanf(params, "%x", &numBytes) != 1) goto error; // If there is any data after the number of bytes, then the format is invalid and it should return an error if (cstrtok(0x00, " ") != 0x00) goto error; dataType = tolower(dataType); // Lowercase the data type if (groupAddress < 0 || groupAddress > 7) goto error; // groupAddress was not in range data[0] = memLoc; // First byte needs to be the memory location according to PCF8570 datasheet slaveAddress |= groupAddress; // ORs the group 2 address to the group 1 address to get slaveAddress I2CHW_bWriteBytes(slaveAddress, data, 1, I2CHW_NoStop); // Write one byte to the RAM, the slaveAddress so it knows who were talking to while (!(I2CHW_bReadI2CStatus() & I2CHW_WR_COMPLETE)); // Wait while it is writing I2CHW_ClrWrStatus(); // Clear the write bit I2CHW_fReadBytes(slaveAddress, data, numBytes, I2CHW_CompleteXfer); // Read numBytes from the RAM, put it in data while(!(I2CHW_bReadI2CStatus() & I2CHW_RD_COMPLETE)); // Wait while it is reading I2CHW_ClrRdStatus(); // Clear the read bit if (dataType == 'a') // If the data type is ASCII { for (i = 0; i < numBytes; ++i) // Loop through each byte UART_PutChar(data[i]); // Put the character in PuTTy UART_PutCRLF(); } else if (dataType == 'h') // If the data type is Hex { for (i = 0; i < numBytes; ++i) // Loop through each byte { csprintf(hexStr, "%X ", data[i]); // csprintf prints into hexStr a hexadecimal with a space UART_PutString(hexStr); // Print hexStr } UART_PutCRLF(); } else goto error; } else goto error; continue; // This is so that the error is skipped when everything goes right error: // This outputs an invalid format message and continues on to read another line UART_CPutString("Invalid format entered. Valid formats are:\r\n\tW [GroupAddress] [MemoryLocation] [h|a] Hex/ASCII\r\n\tR [GroupAddress] [MemoryLocation] [h|a] [NumBytes]\r\n"); } }