chinese直男口爆体育生外卖, 99久久er热在这里只有精品99, 又色又爽又黄18禁美女裸身无遮挡, gogogo高清免费观看日本电视,私密按摩师高清版在线,人妻视频毛茸茸,91论坛 兴趣闲谈,欧美 亚洲 精品 8区,国产精品久久久久精品免费

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

基于STM32的元器件特性測試儀過程

電子森林 ? 來源:電子森林 ? 作者:葉開 ? 2021-04-09 11:42 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

元器件特性測試儀任務要求

通過編程完成對5種以上元器件特性的測量

能夠自動識別元器件

OLED屏幕上通過圖形化的界面顯示各種元器件的符號及測量得到的信息

實驗環(huán)境

硬件:STM32G031G8U6核心板、硬禾學堂制作的底板

軟件:STM32CubeMX、CLion、STM32CubeProgrammer

實現(xiàn)思路

首先進行一個大致的元器件類型的判斷,再精確地測量元器件的各項屬性,最后顯示在OLED屏幕上

各部分的介紹元器件類型的判斷

思路:首先給元器件放電,再輪番給這3pin中的每2pin進行正反地通電,會得到六次結果。將每2pin的結果存儲下來,進行排序后根據元器件特性進行判斷元器件的類型,初步判斷后存下引腳信息并進行參數(shù)的測量和屏幕顯示,具體參考如圖:

49bb3588-9876-11eb-8b86-12bb97331649.png

代碼如下

void QuickCheck() {

QUICKJUDGE result = {0}; //before compare, the result.sat should be sorted

uint8_t BJTFEA[4] = “011”; //BJT

uint8_t DioFea[4] = “001”; //diode/E-MOS

uint8_t ResFea[4] = “002”; //resistance/inductance/charged capacitance

uint8_t CapFea[4] = “000”; //capacitance/no element

uint8_t temp; //交換時用于緩存變量

discharge();

if (QuickTestBetween2Pin(MiddlePort, HighPort, LowPort))

result.Bmh = 1;

/* 共六組測量,代碼省略 */

discharge();

if (QuickTestBetween2Pin(LowPort, HighPort, MiddlePort))

result.Blh = 1;

result.Sta[0] = result.Bmh + result.Bhm + ‘0’;

result.Sta[1] = result.Bml + result.Blm + ‘0’;

result.Sta[2] = result.Bhl + result.Blh + ‘0’;

/// Sort the result.sta from little to big

if (result.Sta[0] 》 result.Sta[1])

temp = result.Sta[0], result.Sta[0] = result.Sta[1], result.Sta[1] = temp;

if (result.Sta[1] 》 result.Sta[2])

temp = result.Sta[1], result.Sta[1] = result.Sta[2], result.Sta[2] = temp;

if (result.Sta[0] 》 result.Sta[2])

temp = result.Sta[0], result.Sta[0] = result.Sta[2], result.Sta[2] = temp;

result.Sta[3] = ‘’;

/// 以下是逐個判斷元器件特征是否和已知特征符合

if (strcmp(result.Sta, CapFea) == 0) {

if (IsCap_Check()) {

ComponentFound = COMPONENT_CAPACITANCE;

Capacitance_Check(*ComponentParam.CAPPARAM.front, *ComponentParam.CAPPARAM.rear);

Capacitance_Display(ComponentParam);

} else {

Error_Report();

}

} else if (strcmp(result.Sta, DioFea) == 0) {

//TODO:Add emos and diode check

//TODO:Sometimes the caps may be metered as a diode

ComponentFound = COMPONENT_DIODE;

if (result.Bml + result.Blm) {

ComponentParam.DiodeParam.front = &MiddlePort;

ComponentParam.DiodeParam.rear = &LowPort;

} else if (result.Bhm + result.Bmh) {

ComponentParam.DiodeParam.front = &MiddlePort;

ComponentParam.DiodeParam.rear = &HighPort;

} else if (result.Blh + result.Bhl) {

ComponentParam.DiodeParam.front = &LowPort;

ComponentParam.DiodeParam.rear = &HighPort;

}

Diode_Check(*ComponentParam.DiodeParam.front, *ComponentParam.DiodeParam.rear);

Diode_Display(ComponentParam);

} else if (strcmp(result.Sta, ResFea) == 0) {

uint8_t ret = 0;

if (result.Bml + result.Blm) {

ret = IsIndOrRes_Check_Between2Pin(MiddlePort, LowPort, HighPort);

ComponentParam.RESPARAM.front = &MiddlePort;

ComponentParam.RESPARAM.rear = &LowPort;

ComponentParam.INDPARAM.front = &MiddlePort;

ComponentParam.INDPARAM.rear = &LowPort;

} else if (result.Bhm + result.Bmh) {

ret = IsIndOrRes_Check_Between2Pin(HighPort, MiddlePort, LowPort);

ComponentParam.RESPARAM.front = &MiddlePort;

ComponentParam.RESPARAM.rear = &HighPort;

ComponentParam.INDPARAM.front = &MiddlePort;

ComponentParam.INDPARAM.rear = &HighPort;

} else if (result.Blh + result.Bhl) {

ret = IsIndOrRes_Check_Between2Pin(LowPort, HighPort, MiddlePort);

ComponentParam.RESPARAM.front = &LowPort;

ComponentParam.RESPARAM.rear = &HighPort;

ComponentParam.INDPARAM.front = &LowPort;

ComponentParam.INDPARAM.rear = &HighPort;

}

if (ret == 1) {

Inductance_Check(*ComponentParam.INDPARAM.front, *ComponentParam.INDPARAM.rear);

Inductance_Display(ComponentParam);

} else if (ret == 2) {

Resistance_Check(*ComponentParam.RESPARAM.front, *ComponentParam.RESPARAM.rear);

Resistance_Display(ComponentParam);

} else {

Error_Report();

}

} else if (strcmp(result.Sta, BJTFEA) == 0) {

ComponentFound = COMPONENT_BJT;

if (result.Bhm + result.Bmh) {

ComponentParam.BJTPARAM.b = &LowPort;

ComponentParam.BJTPARAM.Channel = result.Blm;

} else if (result.Blm + result.Bml) {

ComponentParam.BJTPARAM.b = &HighPort;

ComponentParam.BJTPARAM.Channel = result.Bhl;

} else {

ComponentParam.BJTPARAM.b = &MiddlePort;

ComponentParam.BJTPARAM.Channel = result.Bmh;

}

BJT_Check();

BJT_Display(ComponentParam);

} else {

Error_Report();

}

discharge();

}

區(qū)分電阻和電感

可以給元器件充電后斷電,如果檢測到下端不為低電平,那就是電感。具體代碼如下

/**

* @brief check the element is a inductance or a resistance

* @note firstly,set the fromPin to High and set the toPin to low

* the current direction will like that and the ADC will set here:

* fromPin---element---680r---toPin

* VCC ADC1 GND

* secondly,set the fromPin to Low and set a 470k to protect the io

* the current direction will like that and the ADC will set here:

* fromPin---470k---element---680r---toPin

* GND ADC2 GND

* if it is a inductance the ADC1 and the ADC2 will get a voltage

* while if it is a resistance the ADC1 will get a voltage and the ADC2 will be GND

* @param fromPort

* @param toPort

* @param unusedPort

* @return return 0 if it is no element ,

* return 1 if it is a inductance and

* return 2 if it is a resistance

*/

uint8_t IsIndOrRes_Check_Between2Pin(MEASUREPORT fromPort, MEASUREPORT toPort, MEASUREPORT unusedPort) {

uint16_t adcVol1, adcVol2;

MeasurePort_Init(fromPort, PORT_WITH_NONE, GPIO_PIN_SET);

MeasurePort_Init(toPort, PORT_WITH_680, GPIO_PIN_RESET);

MeasurePort_Init(unusedPort, PORT_FLOATING, GPIO_PIN_RESET);

HAL_GPIO_ReInit(toPort.PIN_WITH_NONE.GPIOx, toPort.PIN_WITH_NONE.GPIO_Pin, GPIO_MODE_ANALOG);

adcVol1 = GetVol(toPort);

MeasurePort_Init(fromPort, PORT_WITH_470K, GPIO_PIN_RESET);

adcVol2 = GetVol(toPort);

if ((adcVol1 《 ADCZERO) && (adcVol2 《 ADCZERO)) {

return 0;

} else if (adcVol2 《 ADCZERO) {

ComponentParam.INDPARAM.front = &fromPort;

ComponentParam.INDPARAM.rear = &toPort;

return 2;

} else {

ComponentParam.RESPARAM.front = &fromPort;

ComponentParam.RESPARAM.rear = &toPort;

return 1;

}

}

電阻的測量

電阻的參數(shù)主要有電阻值,可通過分壓法測量。

首先使用680r電阻,電阻接在上端和下端各測試一次,并計算電阻值。如果電阻阻值過大,可以換用470k電阻。代碼如下

/**

* @brief measure the value of resistance

* @note first measure will set as follows:

* FrontPort---resistance---680r---RearPort

* GND ADC VCC

* second measure will set as follows:

* FrontPort---680r---resistance---RearPormt

* GND ADC VCC

* third and forth measure will use the 470k resistance

* to instead the 680r to have a more accurate value

* when the resistance is big.

* @param FrontPort

* @param RearPort

*/

//TODO:the resistance of the ADC may cause some deviations when use the 470k resistance

void Resistance_Check(MEASUREPORT FrontPort, MEASUREPORT RearPort) {

uint16_t adcget[4];

float res[4];

MEASUREPORT unusedPort = GetUnusedPort(&FrontPort, &RearPort);

/// MeasurePort_Init函數(shù)用于重新初始化一個pin上的3個引腳至指定電阻和電平。

/// 如使用680r電阻,重新初始化其他兩個引腳為浮空高阻,將連接著680r電阻的引腳設為指定電平

MeasurePort_Init(FrontPort, PORT_WITH_NONE, GPIO_PIN_RESET);

MeasurePort_Init(RearPort, PORT_WITH_680, GPIO_PIN_SET);

MeasurePort_Init(unusedPort, PORT_FLOATING, GPIO_PIN_RESET);

/// 重新初始化ADC引腳。ADC引腳一般為提供電阻的那組引腳中未接電阻的引腳

HAL_GPIO_ReInit(RearPort.PIN_WITH_NONE.GPIOx, RearPort.PIN_WITH_NONE.GPIO_Pin, GPIO_MODE_ANALOG);

/// GetVol函數(shù)用于測量指定引腳組中未接電阻那個引腳的電壓

adcget[0] = GetVol(RearPort);

res[0] = 680 / (3300.0 / adcget[0] - 1);

MeasurePort_Init(FrontPort, PORT_WITH_680, GPIO_PIN_RESET);

MeasurePort_Init(RearPort, PORT_WITH_NONE, GPIO_PIN_SET);

MeasurePort_Init(unusedPort, PORT_FLOATING, GPIO_PIN_RESET);

HAL_GPIO_ReInit(FrontPort.PIN_WITH_NONE.GPIOx, FrontPort.PIN_WITH_NONE.GPIO_Pin, GPIO_MODE_ANALOG);

adcget[1] = GetVol(FrontPort);

res[1] = 680 / (adcget[1] / 3300.0) - 680;

if ((res[0] + res[1]) 》 1000) {

/* 與上面的代碼類似,僅將680R改為470K電阻,省略 */

}

if ((res[0] + res[1]) 《= 10000) {

ComponentParam.RESPARAM.ResVal = (uint32_t) (res[0] + res[1]) / 2;

} else if ((res[0] + res[1]) 《= 1000000) {

qsort(res, 4, sizeof(float), cmpfunc);

ComponentParam.RESPARAM.ResVal = (uint32_t) (res[1] + res[2]) / 2;

} else {

ComponentParam.RESPARAM.ResVal = (uint32_t) (res[2] + res[3]) / 2;

}

}

電感的測量

電感的測量可以通過充電后測量放電時間來大致計算出電感值

/**

* @brief charge the inductance and discharge it

* @note get the discharge time and then calculate the value of the inductance

* the current direction will like that and the ADC will set here:

* FrontPort---680r---inductance---RearPort

* VCC ADC GND

* after charge, set the FrontPort to low

* the current direction will like that and the ADC will set here:

* FrontPort---680r---inductance---RearPort

* GND ADC GND

* if the discharge speed is too fast, use the 470k to instead and test again.

* @note calculating the value of the inductance is not verified

* @param FrontPort

* @param RearPort

*/

void Inductance_Check(MEASUREPORT FrontPort, MEASUREPORT RearPort) {

uint16_t adcget1, adcget2;

uint16_t time1, time2;

uint16_t i = 0;

MEASUREPORT unusedPort = GetUnusedPort(&FrontPort, &RearPort);

MeasurePort_Init(FrontPort, PORT_WITH_680, GPIO_PIN_SET);

MeasurePort_Init(RearPort, PORT_WITH_NONE, GPIO_PIN_RESET);

MeasurePort_Init(unusedPort, PORT_FLOATING, GPIO_PIN_RESET);

HAL_GPIO_ReInit(FrontPort.PIN_WITH_NONE.GPIOx, FrontPort.PIN_WITH_NONE.GPIO_Pin, GPIO_MODE_ANALOG);

HAL_Delay(100);

adcget1 = GetVol(FrontPort);

MeasurePort_Init(FrontPort, PORT_WITH_680, GPIO_PIN_RESET);

HAL_GPIO_ReInit(FrontPort.PIN_WITH_NONE.GPIOx, FrontPort.PIN_WITH_NONE.GPIO_Pin, GPIO_MODE_ANALOG);

time1 = HAL_GetTick();

while (i 《 0xffff) {

adcget2 = GetVol(FrontPort);

i++;

if (adcget2 《 ADCZERO) {

break;

}

}

time2 = HAL_GetTick();

if (i 《 100) {

MeasurePort_Init(FrontPort, PORT_WITH_680, GPIO_PIN_SET);

MeasurePort_Init(RearPort, PORT_WITH_NONE, GPIO_PIN_RESET);

MeasurePort_Init(unusedPort, PORT_FLOATING, GPIO_PIN_RESET);

HAL_GPIO_ReInit(FrontPort.PIN_WITH_NONE.GPIOx, FrontPort.PIN_WITH_NONE.GPIO_Pin, GPIO_MODE_ANALOG);

HAL_Delay(100);

adcget1 = GetVol(FrontPort);

MeasurePort_Init(FrontPort, PORT_WITH_470K, GPIO_PIN_RESET);

HAL_GPIO_ReInit(FrontPort.PIN_WITH_NONE.GPIOx, FrontPort.PIN_WITH_NONE.GPIO_Pin, GPIO_MODE_ANALOG);

time1 = HAL_GetTick();

while (i 《 0xffff) {

adcget2 = GetVol(FrontPort);

i++;

if (adcget2 《 ADCZERO) {

break;

}

}

time2 = HAL_GetTick();

ComponentParam.INDPARAM.IndVal = (time2 - time1) / (470000 * log(adcget1 / (float) adcget2)) / 1000;

} else {

ComponentParam.INDPARAM.IndVal = (time2 - time1) / (680 * log(adcget1 / (float) adcget2)) / 1000;

}

}

電容的測量

和電感類似,充電后放電,計算放電的時間。

需要注意的是這邊似乎可能會對有極性的電容進行了反向充電,或者對低耐壓的電容充過壓,暫時沒想到好的解決方法。

/**

* @brief get the value of the capacitance

* @note charge the cap and use a 680r res to discharge the cap

* calculate the value of the cap by the discharge time

* if the discharge speed is too fast, use 470k to instead the 680r

* @warning when checking the electrolytic and tantalum capacitance

* it is important to avoid reverse connection

* @param FrontPort

* @param RearPort

*/

//TODO:the value may not accurate, may caused by HAL_GetTick.

//TODO:Using a timer to caculate the discharge time may better.

void Capacitance_Check(MEASUREPORT FrontPort, MEASUREPORT RearPort) {

uint16_t adcget1, adcget2;

uint16_t time1, time2;

uint16_t i = 0;

MEASUREPORT unusedPort = GetUnusedPort(&FrontPort, &RearPort);

MeasurePort_Init(FrontPort, PORT_WITH_680, GPIO_PIN_SET);

MeasurePort_Init(RearPort, PORT_WITH_NONE, GPIO_PIN_RESET);

MeasurePort_Init(unusedPort, PORT_FLOATING, GPIO_PIN_RESET);

HAL_Delay(100);

adcget1 = GetVol(FrontPort);

MeasurePort_Init(FrontPort, PORT_WITH_680, GPIO_PIN_SET);

HAL_GPIO_ReInit(FrontPort.PIN_WITH_NONE.GPIOx, FrontPort.PIN_WITH_NONE.GPIO_Pin, GPIO_MODE_ANALOG);

time1 = HAL_GetTick();

while (i 《 0xffff) {

adcget2 = GetVol(FrontPort);

i++;

if (adcget2 《 ADCZERO) {

time2 = HAL_GetTick();

break;

}

}

if (i 《 100) {

MeasurePort_Init(FrontPort, PORT_WITH_680, GPIO_PIN_SET);

HAL_Delay(100);

adcget1 = GetVol(FrontPort);

MeasurePort_Init(FrontPort, PORT_WITH_470K, GPIO_PIN_SET);

HAL_GPIO_ReInit(FrontPort.PIN_WITH_NONE.GPIOx, FrontPort.PIN_WITH_NONE.GPIO_Pin, GPIO_MODE_ANALOG);

time1 = HAL_GetTick();

while (i 《 0xffff) {

adcget2 = GetVol(FrontPort);

i++;

if (adcget2 《 ADCZERO) {

time2 = HAL_GetTick();

break;

}

}

ComponentParam.CAPPARAM.CapVal = (time2 - time1) / (470000 * log(adcget1 / (float) adcget2)) / 1000;

} else {

ComponentParam.CAPPARAM.CapVal = (time2 - time1) / (680 * log(adcget1 / (float) adcget2)) / 1000;

}

}

二極管的測量

二極管的測量最為簡單,直接測正反壓降取小的即可

/**

* @brief get the voltage drop of the diode

* @note the current direction will like that and the ADC will set here:

* frontPort---680r---diode---680---rearPort

* VCC ADC1 ADC2 GND

* if the voltage of the diode is close to 3.3V

* exchange the VCC and GND and test it again

* @param FrontPort

* @param RearPort

*/

void Diode_Check(MEASUREPORT FrontPort, MEASUREPORT RearPort) {

uint16_t adcget1, adcget2;

uint16_t dropVol;

MEASUREPORT unusedPort = GetUnusedPort(&FrontPort, &RearPort);

MeasurePort_Init(FrontPort, PORT_WITH_680, GPIO_PIN_SET);

MeasurePort_Init(RearPort, PORT_WITH_680, GPIO_PIN_RESET);

MeasurePort_Init(unusedPort, PORT_FLOATING, GPIO_PIN_RESET);

HAL_GPIO_ReInit(FrontPort.PIN_WITH_NONE.GPIOx, FrontPort.PIN_WITH_NONE.GPIO_Pin, GPIO_MODE_ANALOG);

HAL_GPIO_ReInit(RearPort.PIN_WITH_NONE.GPIOx, RearPort.PIN_WITH_NONE.GPIO_Pin, GPIO_MODE_ANALOG);

adcget1 = GetVol(FrontPort);

adcget2 = GetVol(RearPort);

dropVol = abs(adcget1 - adcget2);

if (dropVol 》 3000) {

MeasurePort_Init(FrontPort, PORT_WITH_680, GPIO_PIN_RESET);

MeasurePort_Init(RearPort, PORT_WITH_680, GPIO_PIN_SET);

MeasurePort_Init(unusedPort, PORT_FLOATING, GPIO_PIN_RESET);

HAL_GPIO_ReInit(FrontPort.PIN_WITH_NONE.GPIOx, FrontPort.PIN_WITH_NONE.GPIO_Pin, GPIO_MODE_ANALOG);

HAL_GPIO_ReInit(RearPort.PIN_WITH_NONE.GPIOx, RearPort.PIN_WITH_NONE.GPIO_Pin, GPIO_MODE_ANALOG);

adcget1 = GetVol(FrontPort);

adcget2 = GetVol(RearPort);

dropVol = abs(adcget1 - adcget2);

MEASUREPORT *temp = ComponentParam.DiodeParam.rear;

ComponentParam.DiodeParam.rear = ComponentParam.DiodeParam.front;

ComponentParam.DiodeParam.front = temp;

}

ComponentParam.DiodeParam.Uon = dropVol;

}

三極管的測量

可以知道得到0次導通的那兩個腳為集電極和發(fā)射極,因為基極與其他兩個集都能導通一次。再檢查基極向集電極或者發(fā)射集是否導通,導通即為NPN,不導通即為PNP。分出三極管類型后測量放大和倒置狀態(tài)下的hFE,也就是beta,大者即為放大狀態(tài)和正確的放大倍數(shù)。

三極管測量hFE的方法:以NPN為例,給基極和集電極通過一個680R電阻接高電平,測量基極和集電極電壓。如果基極電壓不為接近0,表明三極管處于放大狀態(tài),基極電流為(3300mv-adcget1)/680r,集電極電流為(3300mv-adcget2)/680r,hFE即為(3300 - adcget2) / (3300 - adcget1)。如果基極電壓接近0,表明三極管基極電流過大,處于飽和狀態(tài)。增大基極電阻再試一次。

/* 晶體管極性 */

#define P_CHANNEL 1 //NPN

#define N_CHANNEL 0 //PNP

/**

* @brief check the bjt

* @note copy from the program of the CH579

* @attention haven‘t tested yet

*/

void BJT_Check() {

uint16_t adcget1, adcget2, adcget3, adcget4;

uint16_t hfe1, hfe2;

if (ComponentParam.BJTPARAM.Channel == P_CHANNEL) {

if (ComponentParam.BJTPARAM.b == &LowPort) {

discharge();

hfe1 = BJT_Check_NPN(LowPort, MiddlePort, HighPort);

discharge();

hfe2 = BJT_Check_NPN(LowPort, HighPort, MiddlePort);

if (hfe1 》 hfe2) {

ComponentParam.BJTPARAM.c = &MiddlePort;

ComponentParam.BJTPARAM.e = &HighPort;

ComponentParam.BJTPARAM.hFE = hfe1;

} else {

ComponentParam.BJTPARAM.c = &HighPort;

ComponentParam.BJTPARAM.e = &MiddlePort;

ComponentParam.BJTPARAM.hFE = hfe2;

}

} else if (ComponentParam.BJTPARAM.b == &HighPort) {

discharge();

hfe1 = BJT_Check_NPN(HighPort, LowPort, MiddlePort);

discharge();

hfe2 = BJT_Check_NPN(HighPort, MiddlePort, LowPort);

if (hfe1 》 hfe2) {

ComponentParam.BJTPARAM.c = &LowPort;

ComponentParam.BJTPARAM.e = &MiddlePort;

ComponentParam.BJTPARAM.hFE = hfe1;

} else {

ComponentParam.BJTPARAM.c = &MiddlePort;

ComponentParam.BJTPARAM.e = &LowPort;

ComponentParam.BJTPARAM.hFE = hfe2;

}

} else {

discharge();

hfe1 = BJT_Check_NPN(MiddlePort, HighPort, LowPort);

discharge();

hfe2 = BJT_Check_NPN(MiddlePort, LowPort, HighPort);

if (hfe1 》 hfe2) {

ComponentParam.BJTPARAM.c = &HighPort;

ComponentParam.BJTPARAM.e = &LowPort;

ComponentParam.BJTPARAM.hFE = hfe1;

} else {

ComponentParam.BJTPARAM.c = &LowPort;

ComponentParam.BJTPARAM.e = &HighPort;

ComponentParam.BJTPARAM.hFE = hfe2;

}

}

} else {

if (ComponentParam.BJTPARAM.b == &LowPort) {

discharge();

hfe1 = BJT_Check_PNP(LowPort, MiddlePort, HighPort);

discharge();

hfe2 = BJT_Check_PNP(LowPort, HighPort, MiddlePort);

if (hfe1 》 hfe2) {

ComponentParam.BJTPARAM.c = &MiddlePort;

ComponentParam.BJTPARAM.e = &HighPort;

ComponentParam.BJTPARAM.hFE = hfe1;

} else {

ComponentParam.BJTPARAM.c = &HighPort;

ComponentParam.BJTPARAM.e = &MiddlePort;

ComponentParam.BJTPARAM.hFE = hfe2;

}

} else if (ComponentParam.BJTPARAM.b == &HighPort) {

discharge();

hfe1 = BJT_Check_PNP(HighPort, LowPort, MiddlePort);

discharge();

hfe2 = BJT_Check_PNP(HighPort, MiddlePort, LowPort);

if (hfe1 》 hfe2) {

ComponentParam.BJTPARAM.c = &LowPort;

ComponentParam.BJTPARAM.e = &MiddlePort;

ComponentParam.BJTPARAM.hFE = hfe1;

} else {

ComponentParam.BJTPARAM.c = &MiddlePort;

ComponentParam.BJTPARAM.e = &LowPort;

ComponentParam.BJTPARAM.hFE = hfe2;

}

} else {

discharge();

hfe1 = BJT_Check_PNP(MiddlePort, HighPort, LowPort);

discharge();

hfe2 = BJT_Check_PNP(MiddlePort, LowPort, HighPort);

if (hfe1 》 hfe2) {

ComponentParam.BJTPARAM.c = &HighPort;

ComponentParam.BJTPARAM.e = &LowPort;

ComponentParam.BJTPARAM.hFE = hfe1;

} else {

ComponentParam.BJTPARAM.c = &LowPort;

ComponentParam.BJTPARAM.e = &HighPort;

ComponentParam.BJTPARAM.hFE = hfe2;

}

}

}

}

/**

* @brief test the hfe with the imaginary collector and emitter

* @param bPort the base port

* @param cPort the imaginary collector

* @param ePort the imaginary emitter

* @return hfe

*/

uint16_t BJT_Check_PNP(MEASUREPORT bPort, MEASUREPORT cPort, MEASUREPORT ePort) {

uint16_t adcget1, adcget2;

uint16_t hfe;

MeasurePort_Init(ePort, PORT_WITH_680, GPIO_PIN_SET);

MeasurePort_Init(bPort, PORT_WITH_680, GPIO_PIN_RESET);

MeasurePort_Init(cPort, PORT_WITH_NONE, GPIO_PIN_RESET);

HAL_GPIO_ReInit(bPort.PIN_WITH_NONE.GPIOx, bPort.PIN_WITH_NONE.GPIO_Pin, GPIO_MODE_ANALOG);

adcget1 = GetVol(bPort);

if (adcget1 》 ADCZERO) {

HAL_GPIO_ReInit(ePort.PIN_WITH_NONE.GPIOx, ePort.PIN_WITH_NONE.GPIO_Pin, GPIO_MODE_ANALOG);

adcget2 = GetVol(ePort);

hfe = (3300 - adcget2) / adcget1;

} else {

MeasurePort_Init(bPort, PORT_WITH_470K, GPIO_PIN_RESET);

HAL_GPIO_ReInit(bPort.PIN_WITH_NONE.GPIOx, bPort.PIN_WITH_NONE.GPIO_Pin, GPIO_MODE_ANALOG);

adcget1 = GetVol(bPort);

HAL_GPIO_ReInit(ePort.PIN_WITH_NONE.GPIOx, ePort.PIN_WITH_NONE.GPIO_Pin, GPIO_MODE_ANALOG);

adcget2 = GetVol(ePort);

hfe = (470000 * (3300 - adcget2) / 1000) / (680 * adcget1 / 1000) - 1;

}

return hfe;

}

/**

* @brief test the hfe with the imaginary collector and emitter

* @param bPort the base port

* @param cPort the imaginary collector

* @param ePort the imaginary emitter

* @return hfe

*/

uint16_t BJT_Check_NPN(MEASUREPORT bPort, MEASUREPORT cPort, MEASUREPORT ePort) {

uint16_t adcget1, adcget2;

uint16_t hfe;

MeasurePort_Init(ePort, PORT_WITH_NONE, GPIO_PIN_RESET);

MeasurePort_Init(cPort, PORT_WITH_680, GPIO_PIN_SET);

MeasurePort_Init(bPort, PORT_WITH_680, GPIO_PIN_SET);

HAL_GPIO_ReInit(bPort.PIN_WITH_NONE.GPIOx, bPort.PIN_WITH_NONE.GPIO_Pin, GPIO_MODE_ANALOG);

adcget1 = GetVol(bPort);

if (adcget1 》 ADCZERO) {

HAL_GPIO_ReInit(cPort.PIN_WITH_NONE.GPIOx, cPort.PIN_WITH_NONE.GPIO_Pin, GPIO_MODE_ANALOG);

adcget2 = GetVol(cPort);

hfe = (3300 - adcget2) / (3300 - adcget1);

} else {

MeasurePort_Init(bPort, PORT_WITH_470K, GPIO_PIN_RESET);

HAL_GPIO_ReInit(bPort.PIN_WITH_NONE.GPIOx, bPort.PIN_WITH_NONE.GPIO_Pin, GPIO_MODE_ANALOG);

adcget1 = GetVol(bPort);

HAL_GPIO_ReInit(cPort.PIN_WITH_NONE.GPIOx, cPort.PIN_WITH_NONE.GPIO_Pin, GPIO_MODE_ANALOG);

adcget2 = GetVol(cPort);

hfe = (470000 * (3300 - adcget2) / 1000) / (680 * (3300 - adcget1) / 1000);

}

return hfe;

}

OLED的顯示

元器件的各種信息通過一個全局共用體傳遞。OLED使用軟件I2C進行驅動,具體的庫和實現(xiàn)省略,我直播時也有講過,可以參考我整理的一些驅動。

由于macOS上缺少一些取模軟件,這里我暫時使用字符象形一下元件,比如電阻:

void Resistance_Display(COMPONENTPARAMETER ComParam) {

char ch[70];

sprintf(ch, “Res %d-[]-%dR=%d Ohm”,

ConvPinToNum(ComParam.RESPARAM.front-》PIN_WITH_NONE.GPIO_Pin),

ConvPinToNum(ComParam.RESPARAM.rear-》PIN_WITH_NONE.GPIO_Pin),

ComParam.RESPARAM.ResVal);

OLED_Clear();

OLED_ShowString(0, 0, (uint8_t *) ch, 12);

}

一些中間層的函數(shù)

QuickTestBetween2Pin

測試兩腳之間有沒有元件

/**

* @brief test if it is a element between 2 pins

* @note the current direction will like that and the ADC will set here:

* fromPort---element---680r---toPort

* VCC ADC GND

* the toPort will have a 680r resistance to serial connect into the current direction

* and have a no-resistance Pin which will be used as a ADC to

* get the voltage and calculate the equivalent resistance of the element

* @param fromPort the current from, will be set high

* @param toPort the current to, will be set low and use a 680r resistance

* @retval if it is a element between fromPort and toPort

*/

uint8_t QuickTestBetween2Pin(MEASUREPORT fromPort, MEASUREPORT toPort, MEASUREPORT unusedPort) {

MeasurePort_Init(fromPort, PORT_WITH_NONE, GPIO_PIN_SET);

MeasurePort_Init(toPort, PORT_WITH_680, GPIO_PIN_RESET);

MeasurePort_Init(unusedPort, PORT_FLOATING, GPIO_PIN_SET);

HAL_GPIO_ReInit(toPort.PIN_WITH_NONE.GPIOx, toPort.PIN_WITH_NONE.GPIO_Pin, GPIO_MODE_ANALOG);

HAL_Delay(50);

uint16_t ADCVol = GetVol(toPort);

return ADCVol 》 ADCZERO;

}

GetVol

測量指定腳位電壓

/**

* @brief get the voltage of the no-resistance pin in the

* selected pin group.

* @param PinGroup

* @return the average voltage in 5 times test (mv)

*/

uint16_t GetVol(MEASUREPORT PinGroup) {

/**

* arrget[0]-》PA5

* arrget[1]-》PA6

* arrget[2]-》PA7

* arrget[3]-》V_ref

*/

uint16_t arrget[4] = {0};

uint16_t vol = 0, vdda = 0;

uint16_t vref = *(__IO uint16_t *) 0x1FFF75AA;

for (uint8_t i = 0; i 《 5; i++) {

for (uint8_t j = 0; j 《 4; j++) {

arrget[j] += HAL_ADC_Read(&hadc1);

}

}

arrget[3] /= 5;

HAL_ADC_Stop(&hadc1);

vdda = (uint16_t) (vref * 3000.0 / arrget[3]);

switch (PinGroup.PIN_WITH_NONE.GPIO_Pin) {

case GPIO_PIN_5:

vol = arrget[0] * 3300 / 4096.0 / 5;

break;

case GPIO_PIN_6:

vol = arrget[1] * 3300 / 4096.0 / 5;

break;

case GPIO_PIN_7:

vol = arrget[2] * 3300 / 4096.0 / 5;

break;

default:

break;

}

return vol;

}

discharge

給元器件放電

/**

* @brief discharge the element

* @param None

* @retval None

*/

void discharge() {

MeasurePort_Init(HighPort, PORT_WITH_NONE, GPIO_PIN_RESET);

MeasurePort_Init(MiddlePort, PORT_WITH_NONE, GPIO_PIN_RESET);

MeasurePort_Init(LowPort, PORT_WITH_NONE, GPIO_PIN_RESET);

HAL_Delay(50);

}

MeasurePort_Init

重新初始化一個pin上的3個引腳至指定電阻和電平

/**

* @brief Init the selected test group

* @param port the selected test group

* @param mode select the resistance and its pin

* @param PinState test pin power state select

* @retval None

*/

void MeasurePort_Init(MEASUREPORT port, PORTMODE mode, GPIO_PinState PinState) {

switch (mode) {

case PORT_WITH_NONE:

HAL_GPIO_ReInit(port.PIN_WITH_NONE.GPIOx, port.PIN_WITH_NONE.GPIO_Pin, GPIO_MODE_OUTPUT_PP);

HAL_GPIO_ReInit(port.PIN_WITH_680.GPIOx, port.PIN_WITH_680.GPIO_Pin, GPIO_MODE_INPUT);

HAL_GPIO_ReInit(port.PIN_WITH_470K.GPIOx, port.PIN_WITH_470K.GPIO_Pin, GPIO_MODE_INPUT);

HAL_GPIO_WritePin(port.PIN_WITH_NONE.GPIOx, port.PIN_WITH_NONE.GPIO_Pin, PinState);

break;

case PORT_WITH_680:

HAL_GPIO_ReInit(port.PIN_WITH_NONE.GPIOx, port.PIN_WITH_NONE.GPIO_Pin, GPIO_MODE_INPUT);

HAL_GPIO_ReInit(port.PIN_WITH_680.GPIOx, port.PIN_WITH_680.GPIO_Pin, GPIO_MODE_OUTPUT_PP);

HAL_GPIO_ReInit(port.PIN_WITH_470K.GPIOx, port.PIN_WITH_470K.GPIO_Pin, GPIO_MODE_INPUT);

HAL_GPIO_WritePin(port.PIN_WITH_680.GPIOx, port.PIN_WITH_680.GPIO_Pin, PinState);

break;

case PORT_WITH_470K:

HAL_GPIO_ReInit(port.PIN_WITH_NONE.GPIOx, port.PIN_WITH_NONE.GPIO_Pin, GPIO_MODE_INPUT);

HAL_GPIO_ReInit(port.PIN_WITH_680.GPIOx, port.PIN_WITH_680.GPIO_Pin, GPIO_MODE_INPUT);

HAL_GPIO_ReInit(port.PIN_WITH_470K.GPIOx, port.PIN_WITH_470K.GPIO_Pin, GPIO_MODE_OUTPUT_PP);

HAL_GPIO_WritePin(port.PIN_WITH_470K.GPIOx, port.PIN_WITH_470K.GPIO_Pin, PinState);

break;

case PORT_FLOATING:

HAL_GPIO_ReInit(port.PIN_WITH_NONE.GPIOx, port.PIN_WITH_NONE.GPIO_Pin, GPIO_MODE_INPUT);

HAL_GPIO_ReInit(port.PIN_WITH_680.GPIOx, port.PIN_WITH_680.GPIO_Pin, GPIO_MODE_INPUT);

HAL_GPIO_ReInit(port.PIN_WITH_470K.GPIOx, port.PIN_WITH_470K.GPIO_Pin, GPIO_MODE_INPUT);

default:

break;

}

HAL_ADC_Read

進行一次ADC的測量

uint16_t HAL_ADC_Read() {

HAL_ADC_Start(&hadc1);

HAL_ADC_PollForConversion(&hadc1,0xff);

return HAL_ADC_GetValue(&hadc1);

}

HAL_GPIO_ReInit

重新初始化GPIO

void HAL_GPIO_ReInit(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, uint32_t Mode){

HAL_GPIO_DeInit(GPIOx,GPIO_Pin);

GPIO_InitTypeDef GPIO_InitStruct = {0};

GPIO_InitStruct.Pin = GPIO_Pin;

GPIO_InitStruct.Mode = Mode;

GPIO_InitStruct.Pull = GPIO_NOPULL;

HAL_GPIO_Init(GPIOx, &GPIO_InitStruct);

}

ConvPinToNum

將GPIO_PIN_X轉換成引腳1/2/3

uint16_t ConvPinToNum(uint16_t GPIO_Pin) {

if (GPIO_Pin == GPIO_PIN_5) {

return 1;

} else if (GPIO_Pin == GPIO_PIN_6) {

return 2;

} else if (GPIO_Pin == GPIO_PIN_7) {

return 3;

}

return 0;

}

遇到的問題

STM32的ADC采得電壓不是很準確,使用校準后漂移更為離譜

電阻測量時使用470k電阻時測得電阻偏差較大,猜測可能為ADC內阻導致

電容的測量暫未想到較好的方案

FLASH占用較高(約90%),以后可以使用LL庫代替HAL庫來節(jié)省FLASH開支

由于忙于第四期FPGA活動等事,僅針對部分元件為了直播從沁恒于浩然老師的代碼中移植整理了部分代碼,同時電感的代碼僅移植也未經測試

原文標題:基于STM32的元器件特性測試

文章出處:【微信公眾號:FPGA入門到精通】歡迎添加關注!文章轉載請注明出處。

責任編輯:haq

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 電子元器件
    +關注

    關注

    134

    文章

    3864

    瀏覽量

    113481
  • STM32
    +關注

    關注

    2307

    文章

    11150

    瀏覽量

    372410

原文標題:基于STM32的元器件特性測試

文章出處:【微信號:xiaojiaoyafpga,微信公眾號:電子森林】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    LCR測試儀與阻抗分析的區(qū)別分析

    在電子元器件測試領域,LCR測試儀與阻抗分析是兩種常用于測量電感(L)、電容(C)和電阻(R)等參數(shù)的精密儀器。盡管二者在功能上存在交集,但其設計定位、技術能力與應用場景存在顯著差異
    的頭像 發(fā)表于 01-07 14:31 ?107次閱讀
    LCR<b class='flag-5'>測試儀</b>與阻抗分析<b class='flag-5'>儀</b>的區(qū)別分析

    半導體分立器件靜態(tài)參數(shù)測試儀系統(tǒng)STD2000X使用價值和選型參考

    半導體分立器件靜態(tài)參數(shù)測試儀系統(tǒng)在半導體研發(fā)、生產、質量控制及應用中具有重要的使用價值和意義,主要體現(xiàn)在以下幾個方面: 1. 技術價值:確保器件性能與可靠性 半導體分立器件靜態(tài)參數(shù)
    的頭像 發(fā)表于 12-16 16:22 ?203次閱讀
    半導體分立<b class='flag-5'>器件</b>靜態(tài)參數(shù)<b class='flag-5'>測試儀</b>系統(tǒng)STD2000X使用價值和選型參考

    IV曲線測試儀:電子器件的“性能解碼師”

    IV曲線測試儀:電子器件的“性能解碼師” 柏峰【BF-CV1500】在半導體研發(fā)的實驗室、光伏組件的生產車間,或是電子設備的故障診斷現(xiàn)場,IV曲線測試儀都是不可或缺的“核心工具”。它通過精準調控電壓、采集電流,繪制出電子
    的頭像 發(fā)表于 11-12 14:51 ?324次閱讀
    IV曲線<b class='flag-5'>測試儀</b>:電子<b class='flag-5'>器件</b>的“性能解碼師”

    華科智源IGBT靜態(tài)參數(shù)測試儀

    HUSTEC華科智源HUSTEC-1600A-MTIGBT功率器件測試儀一:IGBT功率器件測試儀主要特點華科智源HUSTEC-1600A-MT靜態(tài)
    的頭像 發(fā)表于 10-29 10:39 ?1795次閱讀
    華科智源IGBT靜態(tài)參數(shù)<b class='flag-5'>測試儀</b>

    LCR測試儀如何實現(xiàn)智能化與AI融合

    隨著科技的飛速發(fā)展,人工智能(AI)正以前所未有的速度滲透到各個領域,測試測量行業(yè)也不例外。LCR測試儀作為電子元器件測試的重要工具,其智能化與AI的融合不僅提升了
    的頭像 發(fā)表于 08-08 16:49 ?825次閱讀
    LCR<b class='flag-5'>測試儀</b>如何實現(xiàn)智能化與AI融合

    IGBT靜態(tài)參數(shù)測試儀系統(tǒng)

    HUSTEC華科智源 HUSTEC-1600A-MT IGBT功率器件測試儀 一:IGBT功率器件測試儀主要特點 華科智源HUSTEC-1600A-MT靜態(tài)
    的頭像 發(fā)表于 07-08 17:31 ?1938次閱讀

    充電機特性測試儀是什么?與充放電測試儀區(qū)別

    充電機特性測試儀是一種專門用于檢測和評估直流充電機(或充電裝置)性能的專業(yè)設備,主要應用于電力系統(tǒng)、軌道交通、工業(yè)領域等需要對直流電源系統(tǒng)進行維護和驗證的場景。以下是其核心功能、應用場景及技術特點
    的頭像 發(fā)表于 05-26 16:33 ?665次閱讀
    充電機<b class='flag-5'>特性</b><b class='flag-5'>測試儀</b>是什么?與充放電<b class='flag-5'>測試儀</b>區(qū)別

    LCR測試儀的使用方法與注意事項

    一、引言 LCR測試儀(電感、電容、電阻測試儀)是電子工程領域的核心測量工具,廣泛應用于元件參數(shù)測試、電路調試及產品質量控制。其高精度、多功能特性使其成為實驗室和生產線不可或缺的設備。
    的頭像 發(fā)表于 04-29 10:36 ?7232次閱讀
    LCR<b class='flag-5'>測試儀</b>的使用方法與注意事項

    SC2020晶體管參數(shù)測試儀/?半導體分立器件測試系統(tǒng)介紹

    SC2020晶體管參數(shù)測試儀/?半導體分立器件測試系統(tǒng)-日本JUNO測試儀DTS-1000國產平替 ?專為半導體分立器件
    發(fā)表于 04-16 17:27 ?0次下載

    絕緣電阻測試儀使用方法

    緣電阻測試儀(Insulationresistance testing instrument)又稱數(shù)字絕緣電阻測試儀、兆歐表、智能絕緣電阻測試儀等,是一種常用的儀器設備,用于測量電氣設備的絕緣電阻值。
    的頭像 發(fā)表于 04-12 10:53 ?4220次閱讀
    絕緣電阻<b class='flag-5'>測試儀</b>使用方法

    怎樣使用防水測試儀對手機進行測試

    在當今手機不離手的時代,手機的防水性能越來越重要。那么,如何使用防水測試儀測試手機呢?以下是一個簡單易懂的操作過程的詳細說明。一、前期準備(1)選擇合適的防水測試儀:根據手機的尺寸和
    的頭像 發(fā)表于 02-27 16:58 ?1983次閱讀
    怎樣使用防水<b class='flag-5'>測試儀</b>對手機進行<b class='flag-5'>測試</b>

    LCR測試儀陶瓷電容檢測

    特性,其品質和性能的穩(wěn)定性對于電路的正常運行至關重要。因此,如何對陶瓷電容進行精準檢測,成為了電子產品研發(fā)、生產及維護中的一項核心工作。 LCR測試儀作為一種精確測量電感(Inductor)、電容(Capacitor)和電阻(Resistor)
    的頭像 發(fā)表于 02-17 17:44 ?818次閱讀
    LCR<b class='flag-5'>測試儀</b>陶瓷電容檢測

    行業(yè)不同,防水測試儀咋選?

    行業(yè),防水測試儀需要具備高精度、快速測試的能力。這些產品通常體積小,結構復雜,因此測試儀應具有適應不同尺寸和形狀的樣品測試的微型和多功能特性
    的頭像 發(fā)表于 02-11 11:50 ?844次閱讀
    行業(yè)不同,防水<b class='flag-5'>測試儀</b>咋選?

    光譜測試儀是測什么的_光譜測試儀有輻射嗎

     光譜測試儀,也被稱為光譜或分光,是一種用于將成分復雜的光分解為光譜線的科學儀器。它的測量對象非常廣泛,以下是對光譜測試儀測量內容的詳細歸納:
    的頭像 發(fā)表于 01-28 14:10 ?2647次閱讀

    安立Anritsu S332D 天饋線測試儀駐波比測試儀

    安立Anritsu S332D 天饋線測試儀駐波比測試儀 S332D天饋線測試儀 品牌:Anritsu 安立 型號:S332D 名稱:天饋線測試儀 頻率:100kHz - 3GHz 描
    的頭像 發(fā)表于 01-24 11:38 ?1043次閱讀