Microchip MCP3550 - is the data sheet a load of tosh? - Page 1
Forum section: electronics / general

author: peter-h
author_rank: Super Contributor
timestamp: October 27, 2023, 02:52:49 pm
content: Note the order of the OL and OH bitsDid they really design the chip so these bits change around according to the SPI mode (which is anyway detected implicitly, from the clock phase)??I can confirm experimentally that in Fig 5-7 the bits are depicted wrong. The rest of the bits (including the seven undefined bits on the right) are correct.Oh and while I am at it, the DR bit is not apparently usable because it is undefined until conversion is completeSo one starts the conversion and waits (osDelay(90)) for the 80ms conversion time (-50 version) and then just reads out the data.Other than the above, the device works well.

author: tszaboo
author_rank: Super Contributor
timestamp: October 27, 2023, 04:37:38 pm
content: Oh no, errata in Microchip PIC and errors in their datasheet. This has never happened before.I'm happy if I can buy an opamp from Microchip that doesn't have an errata. "Rail to rail doesn't work, Rev A, voltages below 0.5V and above VCC-0.5V result erroneous output voltages. Workaround: connect voltages closer to mid-rail to inputs."

author: dmills
author_rank: Super Contributor
timestamp: October 27, 2023, 05:34:49 pm
content: Yea, par for the course with them.They also seem to specialise in buying semiconductor vendors with slightly shit chips, see Micrel ethernet sand for example (Does not meet 802.3 spec : Workaround None, going by memory, but it was something like that on an MDI port), errata longer then the (not very good) datasheet.Not a company on my preferred vendor list for opamps I have to admit, it just doesn't seem like a natural fit, but then I am still salty about TI buying Burr Brown and the whole Linear/ADI thing.All datasheets should be read with the understanding that the first few pages were written by marketing, my rule of thumb is that the real thing starts with the fist graph that is not 'typical efficiency' (TI power converters looking at you, also ALL mosfet Ids(on) figures!), and that the rest is a template filled in by the intern with as close to zero understanding as they can get away with.Errata basically tell you mostly about the state of the battle between marketing and engineering at the vendor, the more embarrassing the errors they will admit to the better that fight is going, but just because something is not in the errata does not mean it works until you have verified the functionality.

author: Nominal Animal
author_rank: Super Contributor
timestamp: October 27, 2023, 06:36:16 pm
content: Blargh.If only they sent (OVL|OVH) and (OVL) instead, you'd have first bit (MSB) signal overflow, and the rest would form a 23-bit two's complement result. Now, you need to do several bit ops on the MCU to get the correct result.That was not designed by anyone who has ever written or maintained code that needs to process the results.Quote from: peter-h on October 27, 2023, 02:52:49 pmWell that's stupid for sure.Could you use mode 3 (1,1) instead? After you start the conversion, you keep SCK high, CS low, and wait for the MCP3550 to drive MISO high. Then, you just do a 24-bit transfer to get the 24-bit result, without the useless DR bit.In mode 0,0, keeping SCK low while waiting for rising edge of MISO, I'd probably get rid of the useless DR bit by temporarily switching SCK to a GPIO, and doing an extra SCK pulse (⊓) by hand (keeping it high for a minimum of 90ns).My currently preferred microcontroller, Teensy 4, cannot read the MISO pin while it is assigned to the SPI (LPSPI) – there are two separate GPIO subsystems and each includes their own input part (and only one is DMA-capable); no input part is always connected to the pin – so I'd have to fiddle with the MISO pin control anyway. Doing some SCK shenanigans on top of that is no biggie. It's only 90ns plus transitions and pin control setting, fortunately. On the other hand, Teensy 4 supports 25-bit transfers, so I'd just (EDIT: do mode 3 instead, and) extractOVL|OVH, drop DR, and copyOVLto bits 22-31 to obtain the 32-bit sign-extended twos complement reading. It might be worth it to use LSB bit order, so these bits would be at the low end –– using the three low bits for a lookup table with eight 32-bit entries, a shift right and shift left to drop the unused bits, anRBIT(Cortex-M7 instruction) to reverse the bit order in the 32-bit word, and do an OR with the looked-up 32-bit entry to fix-up the value with sign extension and all.On a 8-bit MCU like AVRs, I'd definitely use SPI mode 3. The MISO pin can be read (PINBbit 3 on ATmega32u4, my favourite 8-bitter), so I'd probably poll it, or electrically connect to a separate input pin that supports rising edge interrupt.Quote from: dmills on October 27, 2023, 05:34:49 pmYep; and this is good for hobbyists like myself to consider when reading datasheets and their errata.

author: nctnico
author_rank: Super Contributor
timestamp: October 27, 2023, 06:45:42 pm
content: Quote from: dmills on October 27, 2023, 05:34:49 pmI agree. Typically I don't use anything from Microchip in my designs. Flash chips from formerly Atmel and chips from formerly Microsemi are an exception. The rest is just utter rubbish.

author: peter-h
author_rank: Super Contributor
timestamp: October 27, 2023, 07:29:11 pm
content: My SPI is shared among a number of peripherals, with re-initialisation as needed (mutexed of course). And it works perfectly.But I found some funny business with the clock being parked differently between peripherals. Should not happen of course but...Here's my crappy codeCode:// Read MCP3550 ADC. Returns a 32 bit signed integer 'value' in the range of +/- 2097152 (2^21).// Returns status bits in an uint: 0=good, 1=OVF POS, 2=OVF NEG, 3=INVALID// The +12% +ve overrange is supported; you also get status=1 then (on +ve readings; makes no// sense on -ve ones due to limited Vcm.// To convert to volts, multiply value (cast to double) by Vref/2097152 where Vref is usually 2.5V.// Execution time is 90ms. Uses the single conversion mode and uses a 90ms wait because we have no way to// monitor the DOUT line separately from it going to SPI DIN. Actual conversion time for the -50 chip is 80ms.uint32_t MCP3550_read(int32_t* value){uint32_t value1 = 0;uint32_t status = 0;static uint8_t valueBuffer;// Must be in main RAM, for DMA to workuint8_t i = 0;// start a single conversion by dropping and raising CS// This needs mutexing too because the chip drives DO when CS=0 and buggers up SPI commsSPI3_Lock();// If current SPI3 init is not this device, initialise itif ( g_spi3_current_config != SPI_MODE_MCP3550 ){MCP3550_cs(1);spi3_set_mode(SPI_MODE_MCP3550);g_spi3_current_config = SPI_MODE_MCP3550;}MCP3550_cs(0);hang_around_us(15);// 8us minMCP3550_cs(1);SPI3_Unlock();// wait for the conversion to complete; min 80ms for MCP3550-50, 67ms for MCP3550-60// Other RTOS tasks can use the SPI during this time.// There is no way around this; even though the 4 byte mode (SPI mode 0,0) returns the// DR bit, this doesn't actually work if you didn't wait long enough.osDelay(90);// Now extract the dataSPI3_Lock();if ( g_spi3_current_config != SPI_MODE_MCP3550 ){MCP3550_cs(1);spi3_set_mode(SPI_MODE_MCP3550);g_spi3_current_config = SPI_MODE_MCP3550;}// Retrieve dataMCP3550_cs(0);hang_around_us(1);// Min time CS=0 to clock// Receive-only, 4 bytes in SPI mode 0,0SPI3_DMA_TransmitReceive(NULL, valueBuffer, 4, false, true, false);MCP3550_cs(1);hang_around_us(1);// Min CS=1 timeSPI3_Unlock();// Get the 32 bits into value1. They are in Valuebuffer as big-endian.for (i = 0; i < 4; i++){value1 <<= 8;value1 |= (uint32_t) valueBuffer;}// The data should be as per SPI 0,0, 4 byte transfer// https://peter-ftp.co.uk/screenshots/202310272618195808.jpg// Shift the 32 bit value to the right to get rid of the 7 spurious bits 0-6value1 >>= 7;// Extract two status bits OL & OH (bits 23,22) into bits 1,0 of status// Note the data sheet has OL and OH bits swapped around randomly in error in the diagrams!!status = (value1>>22) & 0x03;/*for (int i=24;i>0;i--){uint32_t tmp;tmp = (value1>>(i-1))&1;printf("%1ld",tmp);}printf(" st=%ld\r\n",status);*/// Mask off status bits 23,22, leaving the ADC value in 21-0value1 &= 0x003fffff;// Sign extend negative readings - if bit 21 is set, set bits 31 to 22// This would happen spuriously if +ve overflow was active, so we check for that.if ( ( (status & 1) == 0 ) && ( (value1 & 0x200000) != 0) ){value1 |= 0xFFC00000;}*value = (int32_t) value1;return (status);}I considered reconfiguring the SPI pin to GPIO to detect EOC but it would be messy, and would prevent other SPI devices to work during the 90ms.Microchip took over a lot of firms. LAN8742 was originally from who? And a lot of Atmel memory chips. But Atmel wasn't much better.

author: SiliconWizard
author_rank: Super Contributor
timestamp: October 27, 2023, 08:40:43 pm
content: Yeah that looks pretty horrible. I usually favor TI and AD when it comes to DACs and ADCs. But that isn't a guarantee either. I've used a TI I2C DAC that would block the I2C bus until you powered-cycled it if you ever happened to send a command on the bus with a specific list (yes, not even just 1) of slave addresses, which would become "forbidden addresses" so to speak. Very cute. It was mentioned in a sentence in the datasheet although really not clearly (in particular they didn't say what would happen if you used one of these addresses, I found out).Tech documentation is hard and ICs are pretty much set in stone once they have been pushed to production so any design mistake (as long as there's a workaround) ends up being there almost forever. No excuses for that of course but that's just how it works.

author: nctnico
author_rank: Super Contributor
timestamp: October 27, 2023, 09:03:39 pm
content: Quote from: peter-h on October 27, 2023, 07:29:11 pmLAN8742 was from SMSC. Another brand that caused quite a bit of grief (including getting the product through EMC emission testing and making it resilient to survive surge testing).

author: tom66
author_rank: Super Contributor
timestamp: October 27, 2023, 09:35:07 pm
content: Quote from: nctnico on October 27, 2023, 06:45:42 pmTrouble with Microsemi is their datasheets are good but their tools are trash.Compared to Xilinx whose datasheets are hit and miss but their tools are reasonable (if a bit crash-happy, but you can usually work around those issues.)With Microchip I've had issues with datasheets and persistent issues with MPLAB and ICD 3/PICkit 3. And ICD 4 we couldn't get working at all with one specific part. It's annoying because when they do manage to work, Microchip do make some good parts. But it feels like you're spending more time debugging their tools than your own code.Silicon Labs is the worst of all though. EZR32... "EzRadio"... "Simplicity" Studio... ha ha ha... designed by some kind of masochistic cult I can only assume.

author: peter-h
author_rank: Super Contributor
timestamp: October 28, 2023, 08:34:19 am
content: I've been testing this chip a bit more and the spec is impressive. It is in the 0.01% ballpark. Not bad for 3 quid.The Vcm goes down to about -0.3V and certainly full accuracy is maintained down to past -0.2V. This is the case for all these capacitor based delta-sigma chips; they all go a bit below the -ve rail. I limit Vcm anyway explicitly

author: DiTBho
author_rank: Super Contributor
timestamp: October 28, 2023, 09:37:02 am
content: Quote from: Nominal Animal on October 27, 2023, 06:36:16 pmI also usually do these mistakes when I design hypothetical stuff on HDL, but hey? I also usually catch the mistake and fix it as soon as I run the simulator with a piece of usable software.So, probably they just don't check anything and don't get any feedback during the design process

author: Nominal Animal
author_rank: Super Contributor
timestamp: October 28, 2023, 03:11:37 pm
content: Quote from: peter-h on October 27, 2023, 07:29:11 pmRight-o; that's why I asked.Quote from: peter-h on October 27, 2023, 07:29:11 pmDo you have two unused GPIO pins you could use, one input and one output? And room for two additional 5/6-pin cheap ICs? Specifically, 74LVC1G97/74LVC1G58 and a 74AHC1G125?You could doshenaniganswith those, namely detaching MCP3550 SDO and SCK from the SPI bus, use one extra GPIO input pin to monitor MCP3550 SDO, and a GPIO output pin to control MCP3550 /CS. Your current /CS would control whether SDO and SCK are connected to the SPI bus or not.The '1G97 would invert the SCK as seen by MCP3550 so it works in mode 1,1 while the SPI bus uses mode 0,0. '1G58 would not invert.Caveat: this is just an idea, extending from how I'd use a separate GPIO pin on AVRs to monitor SDO for conversion completion; I haven't verified this works well in practice.Quote from: DiTBho on October 28, 2023, 09:37:02 amYep! I don't do HDL/VHDL myself (yet!), but when creating e.g. library interfaces or tools for others to use, Ihave tospend some time investigating the use patterns, or theywill behorrible to use. Same thing, really: cannot just focus on one aspect and leave the practical aspects for others to deal with.

author: peter-h
author_rank: Super Contributor
timestamp: October 29, 2023, 08:39:04 am
content: What I don't get is the total lack of QA within Microchip in this area. Other people must have reported this. The latest DS on their website is from 2014.

author: nctnico
author_rank: Super Contributor
timestamp: October 29, 2023, 05:02:00 pm
content: Quote from: Nominal Animal on October 27, 2023, 06:36:16 pmIt is very possible the solution requires the least amount of silicon area and thus is cheapest to produce. ST is another vendor where you'll find very odd functioning peripherals in their microcontrollers just to cut production costs.

author: peter-h
author_rank: Super Contributor
timestamp: October 29, 2023, 09:04:14 pm
content: I have no issue with a weird bit order; most ADCs etc have weird stuff. The ADS1118 is also weird, for example; look at how it encodes the temp sensor value. But such obvious discrepancies from one DS page to another...

author: tszaboo
author_rank: Super Contributor
timestamp: October 29, 2023, 10:44:03 pm
content: Quote from: peter-h on October 28, 2023, 08:34:19 amOtherwise this ADC is an OK chip. It doesn't have a built-in ref, and I've seen it used for ratiometric measurements, overall good results, thousands of products shipped.Quote from: peter-h on October 29, 2023, 08:39:04 amI worked together with an ex-Microchip employee, who was working on documentation (amongst other things). It's the lack of time, overtime, stress, foreigners who's mother thounge isn't english, combination of these.

author: Nominal Animal
author_rank: Super Contributor
timestamp: October 29, 2023, 11:02:22 pm
content: Quote from: peter-h on October 29, 2023, 09:04:14 pmNah, just logical shift left by 16 bits to left-align it to 32 bits, followed by arithmetic shift right by 18 bits, and you're done. For Cortex-M3/M4/M7, a single 'SBFX rn, rn, #2, #14' does it (typically in a single cycle) in-place.With GCC and Clang, you can use(((int32_t)(((uint32_t)value)<<16))>>18), which will compile to basically optimal code on Cortex-Ms (bit shifts on Cortex-M0/M0+), RISC-V, x86, and x86-64.On 8-bit and 16-bit architectures (ADS1118 is from 2010), just arithmetic shift right by two bits.On an AVR, that's just 'ASR rhi', 'LSR rlo', 'ASR rhi', 'LSR rlo'.On an 8-bit PIC, I count nine instructions: 'CLRFtmp', 'BTFSChi,7', 'DECFtmp,1', 'RRFtmp,1', 'RRFhi,1', 'RRFlo,1', 'RRFtmp,1', 'RRFhi,1', 'RRFlo,1', using an extra temporary byte (although I guess one can use the W accumulator as WREG on later PICs). But PIC are wonky anyway.For the MCP3550, one has to delete one bit (OVH) from the middle of the word, turn 0bABCD... into 0bAACD..., to get the 24-bit two's complement value. Basically, swapping the order of <OVH> and <OVL> bits would have saved a lot of operations, and replacing <OVH> with <OVH OR OVL> made the highest bit into "overflow did occur" with the rest of the bits forming the (two's complement if negative) actual value.Sure, we can deal with it. It just feels .. wonky. Like bicycle pedals that are tilted from horizontal.Quote from: peter-h on October 29, 2023, 09:04:14 pmTrue. The fact that they (Microchip, and others) won'tfixthe damn datasheets really pisses me off.Quote from: tszaboo on October 29, 2023, 10:44:03 pmYup: company culture directed by their leadership. Even profit has its costs.

author: peter-h
author_rank: Super Contributor
timestamp: October 30, 2023, 07:11:24 am
content: Yes the ADS1118 is simple if you do only the minimumIn practice, stuff just gets fatter and fatter...Code:/** Read the specified ADS1118* adc = 0 for internal (ADS1118_ONBOARD), 1 for external (ADS1118_EXTERNAL, 655 board)* mux = 3 bits of mux setting: 4/5/6/7 for AIN0 / AIN1 / AIN2 / AIN3 (see #defines in adc.h)* range = 3 bits of range setting 5/4/3/2/1 for _256mV/_512mV/_1024mV/_2048mV/_4096mV (see #defines in adc.h)* sps = 3 bits of samples per second 8-860 - see #defines in adc.h* temp = 0 for normal mode, 1 to read ADC temperature in degC * 100* Execution time depends on sps.* Uses single conversion mode. First it shifts in the command word (16 bits) and discards the returned value.* Then after waiting for it to finish it shifts in a "NOP" command to grab the returned value.* No other way to do it since we have no way to detect end of conversion.* If temp=1, the conversion speed is forced to the fastest - SPS_860 - and the difference is < 0.1C** The chip temperature mode changes PC11 from the usual pulldown to a pullup, to ensure that an impossible-high* temperature is returned (supposedly 32767 i.e. +327.67 degC) if the analog option is not installed.** In temp=1 mode the sps value must be the SPS_860 one, due to the simple delay used.**/int16_t ADS1118_read ( uint8_t adc, uint8_t mux, uint8_t range, uint8_t sps, uint8_t temp){uint16_t config = 0x8109;// bits 15,9,3,0 are always written with a 1uint16_t waste;uint16_t result = 0;int16_t result2;uint32_t tmp = 0;// Force SPS_860 conversion time if temp=1.if (temp==1) sps = SPS_860;// wait times in ms for 8 16 32 64 128 250 475 860 conversions/sec (allow for +10%)static const uint16_t conv_timer = { 141, 72, 37, 20, 11, 7, 6, 4 };// assemble the config wordconfig |= ( mux & 0x07 ) << 12;config |= ( range & 0x07 ) << 9;config |= ( sps & 0x07 ) << 5;config |= ( temp & 0x01 ) << 4;SPI3_Lock();// If current SPI3 init is not this device, initialise itif ( g_spi3_current_config != SPI_MODE_ADS1118 ){ADS1118_cs(ADS1118_ONBOARD, 1);ADS1118_cs(ADS1118_EXTERNAL, 1);spi3_set_mode(SPI_MODE_ADS1118);g_spi3_current_config = SPI_MODE_ADS1118;}// perform a normal conversion on the selected input// note: if temp=1 then this works the same but all parameters except sps are ignored// start single conversion, discard returned valueconfig |= 0x0002; // load 01 into NOP fieldADS1118_write_read(adc, config, &waste);// wait for ADC to read it (this delay works only if RTOS is running)sps = sps & 0x07;osDelay( conv_timer  );// The above osDelay() fails if this function is called before RTOS is running (which happens// in detect_analog_option()) so we delay manually. This delay is hard coded for the// fastest ADC speedif (temp==1){hang_around_us(3000);}// issue a NOP command but retrieve the valueconfig &= 0xFFF9; // load 00 into NOP fieldif (temp==1){// Enable pullup on PC11 if temp=1 to detect non-installed analog optiontmp = GPIOC->PUPDR;tmp &= ~(3 << 22);// zero both PUPDR11 bitstmp |= (1 << 22);// set them to 01 (pullup)GPIOC->PUPDR = tmp;}ADS1118_write_read(adc, config, &result);if (temp==1){// Revert PC11 to a pulldowntmp = GPIOC->PUPDR;tmp &= ~(3 << 22);// zero both PUPDR11 bitstmp |= (2 << 22);// set them to 10 (pulldown)GPIOC->PUPDR = tmp;}result2 = (int16_t) result; // assume non-temp mode; return signed intif (temp==1){// This is to detect no analog option installed (result=0xffff)// Needs a pullup on PC11 for reading ADS1118 if temp=1if (result!=0xffff){// now we have a 14 bit 2's complement value in leftmost 14 bits, in units of 0.03125C (1/32C)// note: rightmost 2 bits are undefined, and even if they were 00 this will muck up -ve numbersresult = result >> 2; // right-justify itif ( result & 0x2000 ) // sign extend if negative (if bit 13 was 1){result |= 0xc000;}result2 = (int16_t) result;result2 = (result2*100)/32; // get result to be 100 * C}else{result2 = 32767;// return a silly high value}}SPI3_Unlock();return result2;}

author: Nominal Animal
author_rank: Super Contributor
timestamp: October 30, 2023, 03:59:44 pm
content: Quote from: peter-h on October 30, 2023, 07:11:24 amYes, it has lots of options to configure, so if you expose them, you get a lot of code.I prefer a slightly different approach, triggering the measurement separately from reading it, so my own code differs.In particular, I don't like the fact that you keep SPI3 locked for the duration of the conversion.Might be worth it to add a pair ofSPI3_Unlock();,SPI3_Lock();calls?Alternatively, replace the fixed wait with a polling wait while the MISO pin is a GPIO with a pull-up,osDelay()ing in suitably short spurts until ADS1118 pulls MISO low. When theosDelay()is a no-op, that becomes a busy wait, which is what I assume your hang_around_us() function does anyway.C/C++ compilers do not generally optimize(x*100)/32into the mathematically equivalent(x*25)/8(because the result would differ when the multiplication overflows), so we basically have to optimize such ourselves.You do realize that the temperature reading of 0xFFFF may occur naturally, if the two LSB happen to also be 1? That is, a temperature result of 0b11111111111111xx corresponds to a temperature of -0.03125°C.Thus, I'm not certain if your pull-up shenanigans are a reliable indication of the presence of the analog module.Personally, I would do the same extra-GPIO shenanigans with ADS1118 as with MCP3550 I outlined inreply #11, if the SPI bus is used for anything other than the ADC. Thus far, I've got by with just reserving the whole SPI bus for the ADC, though.

author: peter-h
author_rank: Super Contributor
timestamp: October 30, 2023, 05:45:02 pm
content: QuoteYou are right - I changed it. All still worksI struggle to think of a way to avoid the 0xffff case. It means that if you power cycled the unit at ADC chip temp of (what the sensor thinks is) exactly -0.03125C, it would disable the ADC option. I can live with that

author: SiliconWizard
author_rank: Super Contributor
timestamp: October 31, 2023, 05:11:08 am
content: Quote from: peter-h on October 30, 2023, 05:45:02 pmYou can issue a few readings instead of just one, the probability that you'd get several times in a row exactly the same temperature reading - if that was actually the measured temperature - given its resolution here, looks very low. This way you won't get into this potential pitfall, which, while probably still a low probability, is higher than getting the same repeatedly.

author: peter-h
author_rank: Super Contributor
timestamp: October 31, 2023, 06:46:17 am
content: My code which tests for whether the analog option is present is actually looking for > +150C as meaning "not installed".