-
Content Count
52 -
Joined
-
Last visited
-
Days Won
8
Reputation Activity
-
Clavier got a reaction from mph in Implementing an I2C slave device.
Clavier's Short Guide to I²C Slaves on the MSP430x2xx Family
Read section 17.3.4.1 of the User's Guide, and the example code.
Slave mode is somewhat easier than master mode because you do not have to care about getting the transaction sequence correct; you just react to the master's requests.
The slave address is an arbitrary but unique 7-bit number. Just put it into the I2COA ("own address") register; the USCI module will automatically handle transactions to this address.
You do not need to configure a clock source; the clock signal is supplied by the master.
When the master has written a byte, you get an RXIFG interrupt. Your interrupt handler must read that byte from RXBUF. (You can set the TXNACK bit after reading RXBUF, this will tell the master to stop after the following byte.)
When the master wants to read a byte, you get a TXIFG interrupt. Your interrupt handler must write a byte to TXBUF.
If your code is slow, the USCI module will automatically stop the bus via clock stretching until you have reacted.
You can get notifications when start and stop conditions happen (STTIFG and STPIFG), but that is not always necessary.
The I²C protocol itself defines only byte reads and writes. If you have registers, you have to handle the register address yourself. Typically, the first write after a start condition is the register address, and all following writes (and all reads) are from/to the specified register (and often the register address automatically increments).
As a slave, you have no control over what the master does; you must react to any write and read requests at any time. (If you really have nothing to read, just send the last byte again, or some garbage byte.)
-
Clavier got a reaction from energia in Advice for proper chip selection
In general, the G2xx chips have 16 interrupt-capable pins (if they have that many pins at all).
For development, I'd suggest the G2553 on the LaunchPad.
-
Clavier got a reaction from tripwire in Delay() and sleep() have different timing cycles.
The delay() function is part of the official Arduino API. It is implemented with a busy loop, based on the CPU clock.
The sleep() function is not part of the official Arduino API. It powers down the CPU, and measures time based on the VLO, which doesn't have a accurately specified frequency to begin with and has much higher temperature and voltage coefficients than other clock sources.
-
Clavier got a reaction from energia in Delay() and sleep() have different timing cycles.
The delay() function is part of the official Arduino API. It is implemented with a busy loop, based on the CPU clock.
The sleep() function is not part of the official Arduino API. It powers down the CPU, and measures time based on the VLO, which doesn't have a accurately specified frequency to begin with and has much higher temperature and voltage coefficients than other clock sources.
-
Clavier got a reaction from Fmilburn in Delay() and sleep() have different timing cycles.
The delay() function is part of the official Arduino API. It is implemented with a busy loop, based on the CPU clock.
The sleep() function is not part of the official Arduino API. It powers down the CPU, and measures time based on the VLO, which doesn't have a accurately specified frequency to begin with and has much higher temperature and voltage coefficients than other clock sources.
-
Clavier got a reaction from dubnet in Delay() and sleep() have different timing cycles.
The delay() function is part of the official Arduino API. It is implemented with a busy loop, based on the CPU clock.
The sleep() function is not part of the official Arduino API. It powers down the CPU, and measures time based on the VLO, which doesn't have a accurately specified frequency to begin with and has much higher temperature and voltage coefficients than other clock sources.
-
Clavier got a reaction from bluehash in MOSFET Power Circuitry Fails if I2C Pins Initialized First.
Please see table 9 of the LIS3DH datasheet; you are not allowed to apply voltages greater than 0.3 V to the SDA/SCL pins when VACC = 0 V.
You must disconnect these signals before powering down the chip. (And when it's powered down, ACC_INT1 might be floating; you have to deal with that.)
I'd guess VACC gets powered through R8/R9, or through the chip's ESD protection diodes (which go from any I/O to VDD).
-
Clavier got a reaction from bluehash in Sending data via USB to another USB
The G2553 chip itself does not have USB support. You can go through the LaunchPad's "application"/"backchannel" UART; you firmware then just needs to write/read the UART. You also need an application on the host PC to read from one COM port and write to another.
But why use USB? Why can't you control the solenoid directly from the LaunchPad?
-
Clavier got a reaction from Dortol in Sending data via USB to another USB
The G2553 chip itself does not have USB support. You can go through the LaunchPad's "application"/"backchannel" UART; you firmware then just needs to write/read the UART. You also need an application on the host PC to read from one COM port and write to another.
But why use USB? Why can't you control the solenoid directly from the LaunchPad?
-
Clavier got a reaction from NurseBob in Sending data via USB to another USB
The G2553 chip itself does not have USB support. You can go through the LaunchPad's "application"/"backchannel" UART; you firmware then just needs to write/read the UART. You also need an application on the host PC to read from one COM port and write to another.
But why use USB? Why can't you control the solenoid directly from the LaunchPad?
-
Clavier got a reaction from yyrkoon in Implementing an I2C slave device.
Clavier's Short Guide to I²C Slaves on the MSP430x2xx Family
Read section 17.3.4.1 of the User's Guide, and the example code.
Slave mode is somewhat easier than master mode because you do not have to care about getting the transaction sequence correct; you just react to the master's requests.
The slave address is an arbitrary but unique 7-bit number. Just put it into the I2COA ("own address") register; the USCI module will automatically handle transactions to this address.
You do not need to configure a clock source; the clock signal is supplied by the master.
When the master has written a byte, you get an RXIFG interrupt. Your interrupt handler must read that byte from RXBUF. (You can set the TXNACK bit after reading RXBUF, this will tell the master to stop after the following byte.)
When the master wants to read a byte, you get a TXIFG interrupt. Your interrupt handler must write a byte to TXBUF.
If your code is slow, the USCI module will automatically stop the bus via clock stretching until you have reacted.
You can get notifications when start and stop conditions happen (STTIFG and STPIFG), but that is not always necessary.
The I²C protocol itself defines only byte reads and writes. If you have registers, you have to handle the register address yourself. Typically, the first write after a start condition is the register address, and all following writes (and all reads) are from/to the specified register (and often the register address automatically increments).
As a slave, you have no control over what the master does; you must react to any write and read requests at any time. (If you really have nothing to read, just send the last byte again, or some garbage byte.)
-
Clavier got a reaction from Fmilburn in Implementing an I2C slave device.
Clavier's Short Guide to I²C Slaves on the MSP430x2xx Family
Read section 17.3.4.1 of the User's Guide, and the example code.
Slave mode is somewhat easier than master mode because you do not have to care about getting the transaction sequence correct; you just react to the master's requests.
The slave address is an arbitrary but unique 7-bit number. Just put it into the I2COA ("own address") register; the USCI module will automatically handle transactions to this address.
You do not need to configure a clock source; the clock signal is supplied by the master.
When the master has written a byte, you get an RXIFG interrupt. Your interrupt handler must read that byte from RXBUF. (You can set the TXNACK bit after reading RXBUF, this will tell the master to stop after the following byte.)
When the master wants to read a byte, you get a TXIFG interrupt. Your interrupt handler must write a byte to TXBUF.
If your code is slow, the USCI module will automatically stop the bus via clock stretching until you have reacted.
You can get notifications when start and stop conditions happen (STTIFG and STPIFG), but that is not always necessary.
The I²C protocol itself defines only byte reads and writes. If you have registers, you have to handle the register address yourself. Typically, the first write after a start condition is the register address, and all following writes (and all reads) are from/to the specified register (and often the register address automatically increments).
As a slave, you have no control over what the master does; you must react to any write and read requests at any time. (If you really have nothing to read, just send the last byte again, or some garbage byte.)
-
Clavier got a reaction from bluehash in Implementing an I2C slave device.
Clavier's Short Guide to I²C Slaves on the MSP430x2xx Family
Read section 17.3.4.1 of the User's Guide, and the example code.
Slave mode is somewhat easier than master mode because you do not have to care about getting the transaction sequence correct; you just react to the master's requests.
The slave address is an arbitrary but unique 7-bit number. Just put it into the I2COA ("own address") register; the USCI module will automatically handle transactions to this address.
You do not need to configure a clock source; the clock signal is supplied by the master.
When the master has written a byte, you get an RXIFG interrupt. Your interrupt handler must read that byte from RXBUF. (You can set the TXNACK bit after reading RXBUF, this will tell the master to stop after the following byte.)
When the master wants to read a byte, you get a TXIFG interrupt. Your interrupt handler must write a byte to TXBUF.
If your code is slow, the USCI module will automatically stop the bus via clock stretching until you have reacted.
You can get notifications when start and stop conditions happen (STTIFG and STPIFG), but that is not always necessary.
The I²C protocol itself defines only byte reads and writes. If you have registers, you have to handle the register address yourself. Typically, the first write after a start condition is the register address, and all following writes (and all reads) are from/to the specified register (and often the register address automatically increments).
As a slave, you have no control over what the master does; you must react to any write and read requests at any time. (If you really have nothing to read, just send the last byte again, or some garbage byte.)
-
Clavier got a reaction from Fmilburn in Basic MSP430 GPIO Macros
This is how I do my GPIO initialization. It doesn't handle any later GPIO accesses, but it's a nice table, and smaller and faster than configuring the bits one by one.
/* use 0 or 1 to set the output level */ #define OUTPUT 0x00 /* default */ #define INPUT 0x02 #define PULL_DOWN 0x04 #define PULL_UP 0x05 #define REDUCED_DRIVE 0x00 /* default */ #define FULL_DRIVE 0x08 #define GPIO 0x00 /* default */ #define PERIPHERAL 0x10 struct digital_io_init_f5529 { u8 P1[8]; u8 P2[8]; u8 P3[8]; u8 P4[8]; u8 P5[8]; u8 P6[8]; u8 P7[8]; u8 P8[3]; u8 PJ[4]; }; static void init_port(const u8 *init, unsigned int count, uint16_t int base_address) { uint16_t out = 0, dir = 0, ren = 0, ds = 0, sel = 0; uint16_t bit; for (bit = 1; count > 0; init++, bit <<= 1, count--) { if (*init & 1) out |= bit; if (!(*init & INPUT)) dir |= bit; if (*init & PULL_DOWN) ren |= bit; if (*init & FULL_DRIVE) ds |= bit; if (*init & PERIPHERAL) sel |= bit; } HWREG16(base_address + OFS_PAOUT) = out; HWREG16(base_address + OFS_PADIR) = dir; HWREG16(base_address + OFS_PAREN) = ren; HWREG16(base_address + OFS_PADS ) = ds; HWREG16(base_address + OFS_PASEL) = sel; } static void init_ports(const struct digital_io_init_f5529 *init) { init_port(init->P1, 8 + 8, PA_BASE); init_port(init->P3, 8 + 8, PB_BASE); init_port(init->P5, 8 + 8, PC_BASE); init_port(init->P7, 8 + 3, PD_BASE); init_port(init->PJ, 4, PJ_BASE); } void init() { init_ports(&(const struct digital_io_init_f5529){ .P4[4] = PERIPHERAL | OUTPUT, .P4[5] = PERIPHERAL | INPUT, .P7[0] = GPIO | INPUT | PULL_UP, .P7[1] = GPIO | OUTPUT | FULL_DRIVE, /* ... */ }); } -
Clavier got a reaction from pokmo in Analog comparator
Huh? All MSP430 comparator modules are able to raise an interrupt for this.
-
Clavier got a reaction from tripwire in Analog comparator
Huh? All MSP430 comparator modules are able to raise an interrupt for this.
-
Clavier got a reaction from yyrkoon in GPIO interrupts in both directions
Toggling the PxIES bit once has a race condition, when the signal switches again before the interrupt has run. You also have to check the current state of the PxIN bit to ensure that PxIES catches the next edge.
But the easiest way to get interrupts for both edges is to route the signal to two pins.
-
Clavier got a reaction from oPossum in GPIO interrupts in both directions
Toggling the PxIES bit once has a race condition, when the signal switches again before the interrupt has run. You also have to check the current state of the PxIN bit to ensure that PxIES catches the next edge.
But the easiest way to get interrupts for both edges is to route the signal to two pins.
-
Clavier got a reaction from Fred in MOSFET choice for relay switching
There is no flyback diode in this device.
All MOSFETS have a parasitic body diode, but it is no help for you because it is across the source/drain channel, not across the relay.
The NXP's BSS138 model has ESD diodes that protect the gate insulation, but again, these does not help you.
You cannot avoid putting a separate diode across the relay.
-
Clavier got a reaction from Fred in MOSFET choice for relay switching
The 2N7000 would require 5 V to switch on completely, so it is not suitable for the Tiva.
Why do you want to avoid the flyback diode? This would require a high-voltage transistor, and those typically have higher gate threshold voltages.
-
Clavier got a reaction from tripwire in Have feedback for TI? Please share here.
No; the driverlib does not abstract away the differences between the peripherals. For example, you don't have a single SPI API, you have functions for USCI_A_SPI, USCI_B_SPI, EUSCI_A_SPI, and EUSCI_B_SPI. Similarly for Timer_A, Timer_B.
The TI documentation says that the drivers "provide a mechanism that makes it easy to use the device
-
Clavier got a reaction from Fmilburn in Have feedback for TI? Please share here.
No; the driverlib does not abstract away the differences between the peripherals. For example, you don't have a single SPI API, you have functions for USCI_A_SPI, USCI_B_SPI, EUSCI_A_SPI, and EUSCI_B_SPI. Similarly for Timer_A, Timer_B.
The TI documentation says that the drivers "provide a mechanism that makes it easy to use the device
-
Clavier got a reaction from tripwire in Have feedback for TI? Please share here.
Of all the components in an MCU, only the CPU itself is hidden by the compiler; changing anything else would not be portable.
By combining an ARM CPU with the MSP430 peripherals, they allow existing MSP430 program(mer)s to use a faster CPU, without having to do much porting.
The MSP432 is useful for somebody coming from MSP430, not from any other ARM.
-
Clavier got a reaction from zeke in MIDI Booster Pack
And it links to this thread!
And the schematic is capable of improvement: the output connector's pin 2 must be grounded; the unused inverters' inputs must not float; the optocoupler needs a resistor of about 10 k? between pins 5 and 7; and it needs a decoupling capacitor between pins 5 and 8.
-
Clavier got a reaction from Shiv in Parsing "strings" in C - Attempting to parse MQTT payload
If a byte and a char have the same size, casting is no problem.
To avoid modifying the data, don't use zero-terminated strings; just use pointer+length everywhere:
static void parseParameter(const char *param, size_t length); static void handleNameValue(const char *name, size_t nameLength, const char *value, size_t valueLength); static void handleCmd(const char *value, size_t length); static void handleColor(const char *value, size_t length); // etc. void parsePayload(const char *payload, size_t length) { size_t i, paramStartIndex = 0; for (i = 0; i < length; i++) { if (payload[i] == '&') { parseParameter(paramStartIndex, i - paramStartIndex); paramStartIndex = i + 1; } } parseParameter(paramStartIndex, length - paramStartIndex); } static void parseParameter(const char *param, size_t length) { size_t i; for (i = 0; i < length; i++) if (param[i] == '=') { handleNameValue(param, i, ¶m[i + 1], length - (i + 1)); break; } } #define memeq(a,b,sz) (!memcmp(a,b,sz)) #define isString(value, length, literal) (length == sizeof(literal) - 1 && memeq(value, literal, length)) static void handleNameValue(const char *name, size_t nameLength, const char *value, size_t valueLength) { if (isString(name, nameLength, "cmd")) { handleCmd(value, valueLength); } else if (isString(name, nameLength, "color")) { handleColor(value, valueLength); } else if (isString(name, nameLength, "state")) { handleState(value, valueLength); } } static void handleCmd(const char *value, size_t length) { if (isString(value, length, "led")) { remoteCommand.command = Command::Led; } } static void handleColor(const char *value, size_t length) { if (isString(value, length, "red")) { remoteCommand.ledColor = LedColor::red; } else if (isString(value, length, "green")) { remoteCommand.ledColor = LedColor::green; } else if (isString(value, length, "blue")) { remoteCommand.ledColor = LedColor::blue; } } // etc.