I've been trying to get this BLDC demo to work using the 3PH tower module. It blew up fets when I turned it on so I'm auditing every line of code here. The part that inits the adcs raises questions-
calib = ADC1_CLP0;
calib =+ ADC1_CLP1;
calib =+ ADC1_CLP2;
calib =+ ADC1_CLP3;
calib =+ ADC1_CLP4;
calib =+ ADC1_CLPS;
calib = calib >> 1;
calib = calib | 0x8000; // set the MSB
ADC1_PG = calib; // set the plus side gain register
I have not been able to find any information on a "=+" operator, it seems this operator does not exist in C or any language. Stepping through the code it appears to be setting calib equal to the positive value of ADC1_CLPx. This is odd because all of these registers are cast to unsigned ints, you should not have to specify a positive value, and all of it but the last line should be optimized out. I thought maybe whoever wrote this meant "+=", and the calibration section of the datasheet says you need to sum these calibration registers. But after downloading the current BLDC code for the KV chips, it contains the same code with "=+" in it. I also noticed a lot of spelling errors, redundant code, and code mechanisms that are not implemented correctly. Like, why demand that clock defines be set and then hard code all the timing based values? Maybe I'm wrong and the "=+" is supposed to do something that I don't understand since it is still in the code after several years of people using it, surely it would be fixed by now if it were a bug. Maybe I'm the first person ever to use it? Someone from freescale should audit or at least spell check this code. And, if you are going to make us use a precompiled library for the motor driver, at least fix it so it doesn't have main() compiled into it and generates errors out of the box since almost all applications are going to have their own main(). I could be wrong about all this but it appears that an intern started this code and a different intern finished it and nobody at freescale proof read, audited or tested the code.
Hi Josh,
Related source code is for KV10 product ADC module calibration process.
To complete calibration, the user must generate the gain calibration values using the
following procedure:
1. Initialize or clear a 16-bit variable in RAM.
2. Add the plus-side calibration results CLP0, CLP1, CLP2, CLP3, CLP4, and CLPS to
the variable.
3. Divide the variable by two.
4. Set the MSB of the variable.
5. The previous two steps can be achieved by setting the carry bit, rotating to the right
through the carry bit on the high byte and again on the low byte.
6. Store the value in the plus-side gain calibration register PG.
7. Repeat the procedure for the minus-side gain calibration value.
More detailed info, please check KV10 product reference manual chapter 32.4.6 Calibration function at KV10 reference manual.
Below is a typical code for Kinetis ADC module calibration:
/* ADC - Peripheral instance base addresses */
/** Peripheral ADC0 base pointer */
#define ADC0_BASE_PTR ((ADC_MemMapPtr)0x4003B000u)
// Calibrate the ADC in the configuration in which it will be used:
ADC_Cal(ADC0_BASE_PTR); // do the calibration
/****************************************************************************** |
Function 1. Name AUTO CAL ROUTINE
Parameters ADC module pointer points to adc0 or adc1 register map
base address.
Returns Zero indicates success.
Notes Calibrates the ADC16. Required to meet specifications
after reset and before a conversion is initiated.
******************************************************************************/
uint8 ADC_Cal(ADC_MemMapPtr adcmap)
{
unsigned short cal_var;
ADC_SC2_REG(adcmap) &= ~ADC_SC2_ADTRG_MASK ; // Enable Software Conversion Trigger for Calibration Process - ADC0_SC2 = ADC0_SC2 | ADC_SC2_ADTRGW(0);
ADC_SC3_REG(adcmap) &= ( ~ADC_SC3_ADCO_MASK & ~ADC_SC3_AVGS_MASK ); // set single conversion, clear avgs bitfield for next writing
ADC_SC3_REG(adcmap) |= ( ADC_SC3_AVGE_MASK | ADC_SC3_AVGS(AVGS_32) ); // Turn averaging ON and set at max value ( 32 )
ADC_SC3_REG(adcmap) |= ADC_SC3_CAL_MASK ; // Start CAL
while ( (ADC_SC1_REG(adcmap,A) & ADC_SC1_COCO_MASK ) == COCO_NOT ); // Wait calibration end
if ((ADC_SC3_REG(adcmap)& ADC_SC3_CALF_MASK) == CALF_FAIL )
{
return(1); // Check for Calibration fail error and return
}
// Calculate plus-side calibration
cal_var = 0x00;
cal_var = ADC_CLP0_REG(adcmap);
cal_var += ADC_CLP1_REG(adcmap);
cal_var += ADC_CLP2_REG(adcmap);
cal_var += ADC_CLP3_REG(adcmap);
cal_var += ADC_CLP4_REG(adcmap);
cal_var += ADC_CLPS_REG(adcmap);
cal_var = cal_var/2;
cal_var |= 0x8000; // Set MSB
ADC_PG_REG(adcmap) = ADC_PG_PG(cal_var);
// Calculate minus-side calibration
cal_var = 0x00;
cal_var = ADC_CLM0_REG(adcmap);
cal_var += ADC_CLM1_REG(adcmap);
cal_var += ADC_CLM2_REG(adcmap);
cal_var += ADC_CLM3_REG(adcmap);
cal_var += ADC_CLM4_REG(adcmap);
cal_var += ADC_CLMS_REG(adcmap);
cal_var = cal_var/2;
cal_var |= 0x8000; // Set MSB
ADC_MG_REG(adcmap) = ADC_MG_MG(cal_var);
ADC_SC3_REG(adcmap) &= ~ADC_SC3_CAL_MASK ; /* Clear CAL bit */
return(0);
}
Have a great day,
best regards,
Ma Hui
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------