c: CallBack

Jaroslav Buchta jaroslav.buchta na hascomp.cz
Čtvrtek Únor 25 06:03:37 CET 2021


Jen jsem to prolitnul ale tenhle zdrojak se asi nechci snazit ani pochopit.
Sel jsem na to jinak, 2 stavove automaty a jen s cyklicky volanou 
obsluhou main, pro inspiraci v priloze.
Funguje to uz 2 mesice bez selhani nebo restartu na tepelnem cerpadlo.
Blokuje to na max 60us preruseni, tomu jsem se chtel vyhnout a pouzit 
SPI pres DMA (STM32L0), ono by to skvele a na pozadi i fungovalo ale 
kdyby to nekdo zkousel, tak je potreba dat na MOSI latch - stav vystupu 
mezi sekvencemi se mi nepodarilo dostat pod kontrolu, je tam v klidu 
nejaky konec posuvneho registru a zalezi to na predchozim obsahu.

Dne 25.02.2021 v 0:06 Miroslav Draxal napsal(a):
>
> Dobrý večer,
>
> Jedná se o XC8 pro microchip.
>
> Mějme několik místních procedur, každá procedura v jiném kompilovaném 
> modulu (Main.c, CallBack.c,). Tyto procedury se navzájem nemohou 
> ovlivňovat, nejsou v ISR, proto kompilátor pro vnitřní „svoje potřeby“ 
> může použít adresu proměnné, která je ve všech procedurách stejná. 
> (třeba adr. 0x00, kam si ukládá data pro  „svoje potřeby“ )
>
> Existuje technika, jak přinutit, aby pro jeden konkrétní  modul 
> (CallBack.c) použil jedinečné adresy pro „svoje potřeby“.
>
> C nativně neumí CallBack, ale jde to velice jednoduše napsat. Proto 
> píši, že se procedury nemohou ovlivňovat a nejsou v ISR. Kompilátor 
> neví, že z přerušení skáču třeba doprostřed procedury.
>
> Proč to? Používám zpětné volání z ISR. V „voidProc(void)“  v Main.c, 
> se používá adr. proměnné 0x00 pro předání parametru(neovlivním jeho 
> adresu), přijde přerušení, z něj zpětným voláním volám proceduru 
> v CallBack.c, která taky používá adr. proměnné 0x00 ( také to 
> neovlivním), kde se obsah změní, a až se dostanu zpátky z přerušení, 
>  obsah paměti je změněn.
>
> Asi to je prasárna. Ale v systému, kde mi běží na přerušeních všechno, 
> jakoby paralelně, je to zpětné volání fakt dobrá věc. Separované to 
> běží jako z praku, pokud to zavedu do systému, začnou se mi hádat 
> proměnné.
>
> Zasílám k nahlédnutí. Je to zatím neučesané.
>
>
> _______________________________________________
> HW-list mailing list  -  sponsored by www.HW.cz
> Hw-list na list.hw.cz
> http://list.hw.cz/mailman/listinfo/hw-list


------------- další část ---------------
HTML příloha byla odstraněna...
URL: <http://list.hw.cz/pipermail/hw-list/attachments/20210225/6b2a6ea4/attachment.html>
------------- další část ---------------

#include <globaldefs.h>

#define OWSLOTSCOUNT	2
#define OWDEVSLOTMAX	8

//read sampling time in us
#define OWBUSSTABLEDLY	8
#define OWSAMPTIME		10

#define INTR_DIS()	EnterCritical()
#define INTR_ENA()	ExitCritical()


#define OWCMD_SEARCHROM		0xF0
#define OWCMD_READROM		0x33
#define OWCMD_MATCH			0x55
#define OWCMD_SKIPROM		0xCC
#define OWCMD_CONVERTT		0x44
#define OWCMD_WRITESP		0x4E
#define OWCMD_READSP		0xBE

#define OWFAMID_DS18B20		0x28
#define OWFAMID_DS1820		0x10

//static const char *tag = "OWID";


// This table comes from Dallas sample code where it is freely reusable,
// though Copyright (C) 2000 Dallas Semiconductor Corporation

static const uint8_t dscrc_table[] = {
		0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65,
		157,195, 33,127,252,162, 64, 30, 95,  1,227,189, 62, 96,130,220,
		35,125,159,193, 66, 28,254,160,225,191, 93,  3,128,222, 60, 98,
		190,224,  2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255,
		70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89,  7,
		219,133,103, 57,186,228,  6, 88, 25, 71,165,251,120, 38,196,154,
		101, 59,217,135,  4, 90,184,230,167,249, 27, 69,198,152,122, 36,
		248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91,  5,231,185,
		140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205,
		17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80,
		175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238,
		50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115,
		202,148,118, 40,171,245, 23, 73,  8, 86,180,234,105, 55,213,139,
		87,  9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22,
		233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168,
		116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53
};



// Compute a Dallas Semiconductor 8 bit CRC. These show up in the ROM
// and the registers.  (note: this might better be done without to
// table, it would probably be smaller and certainly fast enough
// compared to all those delayMicrosecond() calls.  But I got
// confused, so I use this table from the examples.)

static uint8_t owcrc8(const uint8_t *addr, uint8_t len)
{
	uint8_t crc = 0;

	while (len--)
	{
		crc = dscrc_table[crc ^ *(addr++)];		// pgm_read_byte(dscrc_table + (crc ^ *addr++));
	}

	return crc;

}

//static uint8_t owcrc8_comp(const uint8_t *addr, uint8_t len)
//{
//	uint8_t crc = 0;
//	while (len--)
//	{
//		uint8_t inbyte = *(addr++);
//		for (uint8_t i = 8; i != 0; i--)
//		{
//			uint8_t mix = (crc ^ inbyte) & 0x01;
//			crc >>= 1;
//			if (mix) crc ^= 0x8C;
//			inbyte >>= 1;
//		}
//	}
//
//	return crc;
//
//}

///////////////////////////////////////////////////////////////////////////////



typedef enum owstate_e
{
	owst_Idle,

	owst_DoResetStart,
	owst_ResetDelay,
	owst_ResetWaitPresRls,
	owst_ResetWaitRsth,

	owst_DoCmdW,
	owst_CmdWCmd,
	owst_CmdWData,

	owst_DoCmdR,
	owst_CmdRCmd,
	owst_CmdRData,

	owst_DoCmdRomSrch,
	owst_CmdRomSrchCmd,
	owst_CmdRomSrchR,
	owst_CmdRomSrchW,

	owst_FinOK,
	owst_FinError,
} owstate_t;


typedef enum owdevstate_e
{
	owdst_StartupInit,
	owdst_StartupWait,
	owdst_Idle,
	owdst_ResetIni,
	owdst_ResetIniWait,

	owdst_DoCmdSkipRom,
	owdst_WaitCmdSkipRom,

	owdst_DoCmdReadRom,
	owdst_WaitReadRom,

	owdst_DoRomSearch,
	owdst_RomSearchResetStart,
	owdst_RomSearchResetWait,
	owdst_RomSearchFindNext,

	owdst_DoStartConv,
	owdst_ConvResetStart,
	owdst_ConvResetWait,
	owdst_ConvSkipRomCmd,
	owdst_ConvStartConvCmd,
	owdst_ConvWaitFinish,
	owdst_ReadSpResetStart,
	owdst_ReadSpResetWait,
	owdst_ReadSpMatchRom,
	owdst_ReadSpReadData,


	owdst_Wait,
	owdst_Error,
} owdevstate_t;


typedef struct owSlotData_s
{
	owdev_data_t	devData[OWDEVSLOTMAX];
	uint32_t 		tckAction;
	owstate_t 		owstate;
	uint8_t 		owdata[9];
	uint8_t 		owbitcntr;
	uint8_t 		owbytecntr;
	uint8_t 		owcmd;
	uint8_t 		owcnt;			// universal counter
	uint8_t 		devCnt;
	uint8_t 		devPosPart;

	owdevstate_t	owdevstate;
	uint32_t 		tckDevOp;
	uint32_t 		tckDevTout;
	uint8_t 		slotId;
} owSlotData_t;


static owSlotData_t slotsData[OWSLOTSCOUNT];

static inline uint16_t slotIdx2Id(int idx)
{
	return (uint16_t)1 << idx;
}

static inline void owPinSet(uint16_t slotId, bool state)
{
	if (slotId == slotIdx2Id(0))
	{
		HAL_GPIO_WritePin(OWSLOT1_OUT_GPIO_Port, OWSLOT1_OUT_Pin, state ? GPIO_PIN_RESET : GPIO_PIN_SET);
	}
	else
	{
		HAL_GPIO_WritePin(OWSLOT2_OUT_GPIO_Port, OWSLOT2_OUT_Pin, state ? GPIO_PIN_RESET : GPIO_PIN_SET);
	}
}

static inline bool owPinGet(uint16_t slotId)
{
	if (slotId == slotIdx2Id(0))
	{
		return (HAL_GPIO_ReadPin(OWSLOT1_IN_GPIO_Port, OWSLOT1_IN_Pin) == GPIO_PIN_SET);
	}
	else
	{
		return (HAL_GPIO_ReadPin(OWSLOT2_IN_GPIO_Port, OWSLOT2_IN_Pin) == GPIO_PIN_SET);
	}
}


static bool owPresenceTest(owSlotData_t *slot)
{
	INTR_DIS();
	owPinSet(slot->slotId, true);
	uint16_t tckd = GetUsTicksDist(0);
	while (GetUsTicksDist(tckd) < OWBUSSTABLEDLY);	//wait to sample
	if (!owPinGet(slot->slotId))
	{	// short to ground error
		INTR_ENA();
		return false;
	}
	uint8_t samps = 3;
	while (GetUsTicksDist(tckd) <= 60)
	{
		if (!owPinGet(slot->slotId))
		{
			samps --;
		}
		else
		{
			samps = 3;
		}

		if (samps == 0)
		{
			// presence pulse OK
			INTR_ENA();
			return true;
		}
	}
	// presence pulse missing
	INTR_ENA();
	return false;
}

static void owWriteBit (owSlotData_t *slot, uint8_t b, uint8_t pos)
{
	INTR_DIS();
	owPinSet(slot->slotId, false);
	uint16_t tckd = GetUsTicksDist(0);
	if ((b & (1<<pos)) != 0)
	{
		while (GetUsTicksDist(tckd) < 2);
		owPinSet(slot->slotId, true);
	}
	else
	{
		while (GetUsTicksDist(tckd) < 60);
		owPinSet(slot->slotId, true);
	}
	INTR_ENA();
	while (GetUsTicksDist(tckd) < 60 + OWBUSSTABLEDLY);
}

static void owReadBit (owSlotData_t *slot, uint8_t *b, uint8_t pos)
{
	INTR_DIS();
	owPinSet(slot->slotId, false);
	uint16_t tckd = GetUsTicksDist(0);
	while (GetUsTicksDist(tckd) < 2);
	owPinSet(slot->slotId, true);
	while (GetUsTicksDist(tckd) < OWSAMPTIME);
	bool pin = owPinGet(slot->slotId);
	INTR_ENA();
	if (pin)
	{
		*b |= 1 << pos;
	}
	else
	{
		*b &= ~(1 << pos);
	}
	while (GetUsTicksDist(tckd) < 60 + OWBUSSTABLEDLY);
}



static void StartCommandW(owSlotData_t *slot, uint8_t cmd, uint16_t cnt, uint8_t *data, uint32_t tckms)
{
	if (cnt > 8) Error_Handler();
	slot->owcmd = cmd;
	slot->owcnt = cnt;
	if (cnt != 0 && data != NULL)
	{
		memcpy ((void *)slot->owdata, (void *)data, cnt);
	}
	slot->tckDevOp = tckms;
	slot->owstate = owst_DoCmdW;
}

static void StartCommandR(owSlotData_t *slot, uint8_t cmd, uint16_t cnt, uint32_t tckms)
{
	if (cnt > 8) Error_Handler();
	slot->owcmd = cmd;
	slot->owcnt = cnt;
	memset ((void *)slot->owdata, 0, sizeof(slot->owdata));
	slot->tckDevOp = tckms;
	slot->owstate = owst_DoCmdR;
}

static void StartCommandSearch(owSlotData_t *slot, uint32_t tckms, bool bInit)
{
	slot->owcmd = OWCMD_SEARCHROM;
	slot->owcnt = 0;	// match bits counter
	if (bInit)
	{
		slot->devCnt = 0;
		slot->devPosPart = 0;
		for (int idx=0; idx< OWDEVSLOTMAX; idx++)
		{
			memset ((void *)&slot->devData[idx], 0, sizeof(owdev_data_t));
		}
	}
	slot->tckDevOp = tckms;
	slot->owstate = owst_DoCmdRomSrch;
}


static void SetDeviceRomBit(owdev_data_t *dev, uint8_t bitpos, uint8_t bit)
{
	if (bit)
	{
		dev->romId[bitpos/8] |= 1 << (bitpos & 0x07);
	}
	else
	{
		dev->romId[bitpos/8] &= ~(1 << (bitpos & 0x07));
	}
}

static uint8_t GetDeviceRomBit(owdev_data_t *dev, uint8_t bitpos)
{
	return (dev->romId[bitpos/8] & (1 << (bitpos & 0x07))) != 0 ? 1 : 0;
}

static void owSlotService(owSlotData_t *slot, uint32_t tckus)
{
	switch (slot->owstate)
	{
	case owst_Idle:
		break;
	case owst_DoResetStart:
		owPinSet(slot->slotId, false);
		slot->tckAction = tckus;
		slot->owstate = owst_ResetDelay;
		break;
	case owst_ResetDelay:
		if (tckus - slot->tckAction >= 500)
		{
			slot->tckAction = tckus;
			if (owPresenceTest(slot))
			{
				slot->owstate = owst_ResetWaitPresRls;
			}
			else
			{
				slot->owstate = owst_FinError;
			}
		}
		break;
	case owst_ResetWaitPresRls:
		if (owPinGet(slot->slotId))
		{
			slot->owstate = owst_ResetWaitRsth;
		}
		else
		{
			if (tckus - slot->tckAction > 240)
			{
				slot->owstate = owst_FinError;
			}
		}
		break;
	case owst_ResetWaitRsth:
		if (tckus - slot->tckAction >= 500)
		{
			slot->owstate = owst_FinOK;
		}
		break;

	case owst_DoCmdW:
		slot->owbitcntr = 0;
		slot->owbytecntr = 0;
		slot->owstate = owst_CmdWCmd;
		break;
	case owst_CmdWCmd:
		owWriteBit(slot, slot->owcmd, slot->owbitcntr++);
		if (slot->owbitcntr == 8)
		{
			if (slot->owcnt != 0)
			{
				slot->owbitcntr = 0;
				slot->owstate = owst_CmdWData;
			}
			else
			{
				slot->owstate = owst_FinOK;
			}
		}
		break;
	case owst_CmdWData:
		owWriteBit(slot, slot->owdata[slot->owbytecntr], slot->owbitcntr++);
		if (slot->owbitcntr == 8)
		{
			slot->owbitcntr = 0;
			slot->owbytecntr++;
			if (slot->owbytecntr == slot->owcnt)
			{
				slot->owstate = owst_FinOK;
			}
		}
		break;

	case owst_DoCmdR:
		slot->owbitcntr = 0;
		slot->owbytecntr = 0;
		slot->owstate = owst_CmdRCmd;
		break;
	case owst_CmdRCmd:
		owWriteBit(slot, slot->owcmd, slot->owbitcntr++);
		if (slot->owbitcntr == 8)
		{
			if (slot->owcnt != 0)
			{
				slot->owbitcntr = 0;
				slot->owstate = owst_CmdRData;
			}
			else
			{
				slot->owstate = owst_FinOK;
			}
		}
		break;
	case owst_CmdRData:
		owReadBit(slot, &slot->owdata[slot->owbytecntr], slot->owbitcntr++);
		if (slot->owbitcntr == 8)
		{
			slot->owbitcntr = 0;
			slot->owbytecntr++;
			if (slot->owbytecntr == slot->owcnt)
			{
				slot->owstate = owst_FinOK;
			}
		}
		break;

	case owst_DoCmdRomSrch:
		slot->owbitcntr = 0;
		slot->owstate = owst_CmdRomSrchCmd;
		break;
	case owst_CmdRomSrchCmd:
		owWriteBit(slot, slot->owcmd, slot->owbitcntr++);
		if (slot->owbitcntr == 8)
		{
			{
				slot->owbitcntr = 0;
				slot->owstate = owst_CmdRomSrchR;
			}
		}
		break;
	case owst_CmdRomSrchR:
		{
			uint8_t bits = 0;
			owReadBit(slot, &bits, 0);
			owReadBit(slot, &bits, 1);
			slot->owstate = owst_CmdRomSrchW;
			if (slot->owbitcntr >= slot->devData[slot->devCnt].bitpos)
			{
				switch (bits)
				{
					case 0x00:		// collision, create next tree item
						SetDeviceRomBit(&slot->devData[slot->devCnt], slot->owbitcntr, 0);
						if (slot->devPosPart + 1 < OWDEVSLOTMAX)
						{
							slot->devPosPart++;
							memcpy ((void *)slot->devData[slot->devPosPart].romId, (void *)slot->devData[slot->devCnt].romId, 8);
							SetDeviceRomBit(&slot->devData[slot->devPosPart], slot->owbitcntr, 1);
							slot->devData[slot->devPosPart].bitpos = slot->owbitcntr+1;	// bit position of first not match bit
						}
						break;
					case 0x01:		// bit 1
						SetDeviceRomBit(&slot->devData[slot->devCnt], slot->owbitcntr, 1);
						break;
					case 0x02:		// bit 0
						SetDeviceRomBit(&slot->devData[slot->devCnt], slot->owbitcntr, 0);
						break;
					case 3:			// error
						slot->owstate = owst_FinError;
						break;
				}
			}
		}
		break;
	case owst_CmdRomSrchW:
		owWriteBit(slot, GetDeviceRomBit(&slot->devData[slot->devCnt], slot->owbitcntr++), 0);
		if (slot->owbitcntr == 64)
		{
			uint8_t crc = owcrc8(slot->devData[slot->devCnt].romId, 8);
			if (crc != 0)
			{
				slot->owstate = owst_FinError;
			}
			else
			{
				slot->devData[slot->devCnt].flags = OWDEV_FL_PRESENT;
				slot->devCnt++;
				slot->owstate = owst_FinOK;
			}
		}
		else
		{
			slot->owstate = owst_CmdRomSrchR;
		}
		break;


	case owst_FinOK:
		break;
	case owst_FinError:
		break;
	}

}

static void owDevService(owSlotData_t *slot, uint32_t tckms)
{
	switch (slot->owdevstate)
	{
	case owdst_StartupInit:
		slot->tckDevOp = tckms;
		slot->owdevstate = owdst_StartupWait;
		break;
	case owdst_StartupWait:
		if (tckms - slot->tckDevOp >= 1000)
		{
			slot->tckDevOp = tckms;
			slot->owdevstate = owdst_Idle;
		}
		break;
	case owdst_Idle:
		slot->owdevstate = owdst_DoRomSearch;
		break;
	case 	owdst_ResetIni:
		slot->tckDevOp = tckms;
		slot->owstate = owst_DoResetStart;
		slot->owdevstate = owdst_ResetIniWait;
		break;
	case 	owdst_ResetIniWait:
		if (slot->owstate == owst_FinOK)
		{
			slot->owstate = owst_Idle;
			slot->owdevstate = owdst_DoCmdReadRom;	// SkipRom;
		}
		else if (slot->owstate == owst_FinError)
		{
			slot->owstate = owst_Idle;
			slot->tckDevOp = tckms;
			slot->owdevstate = owdst_Error;
		}
		break;

	case owdst_DoCmdSkipRom:
		StartCommandW(slot, OWCMD_SKIPROM, 0, NULL, tckms);
		slot->owdevstate = owdst_WaitCmdSkipRom;
		break;
	case owdst_WaitCmdSkipRom:
		if (slot->owstate == owst_FinOK)
		{
			slot->owstate = owst_Idle;
			slot->owdevstate = owdst_DoCmdReadRom;
		}
		else if (slot->owstate == owst_FinError)
		{
			slot->owstate = owst_Idle;
			slot->tckDevOp = tckms;
			slot->owdevstate = owdst_Error;
		}
		break;

	case owdst_DoCmdReadRom:
		StartCommandR(slot, OWCMD_READROM, 8, tckms);
		slot->owdevstate = owdst_WaitReadRom;
		break;
	case owdst_WaitReadRom:
		if (slot->owstate == owst_FinOK)
		{
			slot->owstate = owst_Idle;
			uint8_t crc = owcrc8(slot->owdata, 7);
			if (crc == slot->owdata[7])
			{
				slot->owdevstate = owdst_Idle;
			}
			else
			{
				slot->tckDevOp = tckms;
				slot->owdevstate = owdst_Error;
			}
		}
		else if (slot->owstate == owst_FinError)
		{
			slot->owstate = owst_Idle;
			slot->tckDevOp = tckms;
			slot->owdevstate = owdst_Error;
		}
		break;



	case owdst_DoRomSearch:
		slot->devCnt = 0;
		slot->devPosPart = 0;
		slot->owdevstate = owdst_RomSearchResetStart;
		break;
	case owdst_RomSearchResetStart:
		slot->tckDevOp = tckms;
		slot->owstate = owst_DoResetStart;
		slot->owdevstate = owdst_RomSearchResetWait;
		break;
	case owdst_RomSearchResetWait:
		if (slot->owstate == owst_FinOK)
		{
			slot->owstate = owst_Idle;
			StartCommandSearch(slot, tckms, slot->devCnt == 0);
			slot->owdevstate = owdst_RomSearchFindNext;
		}
		else if (slot->owstate == owst_FinError)
		{
			slot->owstate = owst_Idle;
			slot->tckDevOp = tckms;
			slot->owdevstate = owdst_Error;
		}
		break;
	case owdst_RomSearchFindNext:
		if (slot->owstate == owst_FinOK)
		{
			slot->owstate = owst_Idle;
			if (slot->devCnt > slot->devPosPart)
			{
				slot->tckDevOp = tckms;
				slot->owdevstate = owdst_DoStartConv;
			}
			else
			{
				slot->owdevstate = owdst_RomSearchResetStart;
			}
		}
		else if (slot->owstate == owst_FinError)
		{
			slot->owstate = owst_Idle;
			slot->tckDevOp = tckms;
			slot->owdevstate = owdst_Error;
		}
		break;

	// start conversion and read data from sensors
	case owdst_DoStartConv:
		slot->devPosPart = 0;
		slot->owdevstate = owdst_ConvResetStart;
		break;
	case owdst_ConvResetStart:
		slot->tckDevOp = tckms;
		slot->owstate = owst_DoResetStart;
		slot->owdevstate = owdst_ConvResetWait;
		break;
	case owdst_ConvResetWait:
		if (slot->owstate == owst_FinOK)
		{
			slot->owstate = owst_Idle;
			StartCommandW(slot, OWCMD_SKIPROM, 0, NULL, tckms);
			slot->owdevstate = owdst_ConvSkipRomCmd;
		}
		else if (slot->owstate == owst_FinError)
		{
			slot->owstate = owst_Idle;
			slot->tckDevOp = tckms;
			slot->owdevstate = owdst_Error;
		}
		break;
	case owdst_ConvSkipRomCmd:
		if (slot->owstate == owst_FinOK)
		{
			slot->owstate = owst_Idle;
			StartCommandW(slot, OWCMD_CONVERTT, 0, NULL, tckms);
			slot->owdevstate = owdst_ConvStartConvCmd;
		}
		else if (slot->owstate == owst_FinError)
		{
			slot->owstate = owst_Idle;
			slot->tckDevOp = tckms;
			slot->owdevstate = owdst_Error;
		}
		break;
	case owdst_ConvStartConvCmd:
		if (slot->owstate == owst_FinOK)
		{
			slot->owstate = owst_Idle;
			slot->tckDevOp = tckms;
			slot->tckDevTout = tckms;
			slot->owdevstate = owdst_ConvWaitFinish;
		}
		else if (slot->owstate == owst_FinError)
		{
			slot->owstate = owst_Idle;
			slot->tckDevOp = tckms;
			slot->owdevstate = owdst_Error;
		}
		break;
	case owdst_ConvWaitFinish:
		if (tckms - slot->tckDevOp >= 10)
		{
			slot->tckDevOp = tckms;
			uint8_t b = 0;
			owReadBit(slot, &b, 0);
			if (b)
			{
				slot->owdevstate = owdst_ReadSpResetStart;
			}
			else if (tckms - slot->tckDevTout > 1000)
			{	// timeout error
				slot->tckDevOp = tckms;
				slot->owdevstate = owdst_Error;
			}
		}
		break;

	case owdst_ReadSpResetStart:
		slot->tckDevOp = tckms;
		if (slot->devPosPart >= slot->devCnt)
		{	// read data finished
			slot->owdevstate = owdst_Wait;
		}
		else
		{
			slot->owstate = owst_DoResetStart;
			slot->owdevstate = owdst_ReadSpResetWait;
		}
		break;
	case owdst_ReadSpResetWait:
		if (slot->owstate == owst_FinOK)
		{
			slot->owstate = owst_Idle;
			StartCommandW(slot, OWCMD_MATCH, 8, slot->devData[slot->devPosPart].romId, tckms);
			slot->owdevstate = owdst_ReadSpMatchRom;
		}
		else if (slot->owstate == owst_FinError)
		{
			slot->owstate = owst_Idle;
			slot->tckDevOp = tckms;
			slot->owdevstate = owdst_Error;
		}
		break;
	case owdst_ReadSpMatchRom:
		if (slot->owstate == owst_FinOK)
		{
			slot->owstate = owst_Idle;
			StartCommandR(slot, OWCMD_READSP, 9, tckms);
			slot->owdevstate = owdst_ReadSpReadData;
		}
		else if (slot->owstate == owst_FinError)
		{
			slot->owstate = owst_Idle;
			slot->tckDevOp = tckms;
			slot->owdevstate = owdst_Error;
		}
		break;
	case owdst_ReadSpReadData:
		if (slot->owstate == owst_FinOK)
		{
			slot->owstate = owst_Idle;
			uint8_t crc = owcrc8(slot->owdata, 9);
			if (crc != 0)
			{
				slot->tckDevOp = tckms;
				slot->owdevstate = owdst_Error;
			}
			else
			{
				owdev_data_t *dd = &slot->devData[slot->devPosPart];
				if (dd->romId[0] == OWFAMID_DS18B20)
				{
					int32_t t = ((int32_t)slot->owdata[0]) | (((int32_t)slot->owdata[1]) << 8);
					if ((t & 0x8000) != 0) t |= 0xffff0000;	//sign extension
					t *= 100;
					t /= 16;
					dd->temperature = (int16_t)(t & 0xffff);
					dd->timeStamp = tckms;
				}
				else if (dd->romId[0] == OWFAMID_DS1820)
				{
					int32_t t = ((int32_t)slot->owdata[0]) | (((int32_t)slot->owdata[1]) << 8);
					if ((t & 0x8000) != 0) t |= 0xffff0000;	//sign extension
					t &= 0xfffffffe;						//truncate LSB
					t *= 50;
					t += (((int32_t)(slot->owdata[7] - slot->owdata[6]))*100)/(int32_t)slot->owdata[7] - 25;
					dd->temperature = (int16_t)(t & 0xffff);
					dd->timeStamp = tckms;
				}
				slot->devPosPart++;
				slot->owdevstate = owdst_ReadSpResetStart;
			}
		}
		else if (slot->owstate == owst_FinError)
		{
			slot->owstate = owst_Idle;
			slot->tckDevOp = tckms;
			slot->owdevstate = owdst_Error;
		}
		break;


	// finish state and manage next cycle
	case owdst_Wait:
		if (tckms - slot->tckDevOp >= 100)
		{
			slot->owdevstate = owdst_DoStartConv;
		}
		break;
	case owdst_Error:
		if (tckms - slot->tckDevOp >= 2000)
		{
			slot->owdevstate = owdst_Idle;
		}
		break;
	}
}


void owdev_Init()
{
	memset ((void *)slotsData, 0x00, sizeof(slotsData));
	for (int idx=0; idx < OWSLOTSCOUNT; idx++)
	{
		slotsData[idx].slotId = slotIdx2Id(idx);
		slotsData[idx].owstate = owst_Idle;
		slotsData[idx].owdevstate = owdst_StartupInit;
	}
}

void owdev_Service()
{
//	DIAG1_S();
//	for (int idx=0; idx < 1; idx++)
	for (int idx=0; idx < OWSLOTSCOUNT; idx++)
	{
		owSlotService(&slotsData[idx], (uint32_t)GetUsTicks());
		owDevService(&slotsData[idx], HAL_GetTick());
		for (int id=0; id<OWDEVSLOTMAX; id++)
		{
			slotsData[idx].devData[id].slotId = idx;
		}
	}
//	DIAG1_R();
}



owdev_data_t *owdev_GetData(int idx)
{
	for (int islot = 0; islot < OWSLOTSCOUNT; islot++)
	{
		if (idx >= slotsData[islot].devCnt)
		{
			idx -= slotsData[islot].devCnt;
			continue;
		}
		return &slotsData[islot].devData[idx];
	}
	return NULL;
}

static inline bool testIdMatch(uint8_t *id1, uint8_t *id2)
{
	if (*((uint64_t *)id1) != *((uint64_t *)id2))
	{
		return false;
	}
//	for (int idx=0; idx<7; idx++)
//	{
//		if (id1[idx] != id2[idx]) return false;
//	}
	return true;
}

extern owdev_data_t *owdev_GetDataById(uint8_t *id)
{
	for (int idx=0;;idx++)
	{
		owdev_data_t *dd = owdev_GetData(idx);
		if (dd == NULL) break;
		if (testIdMatch(id, dd->romId))
		{
			return dd;
		}
	}
	return NULL;
}
------------- další část ---------------
/*
 * SystemExt.h
 *
 *  Created on: 10. 2. 2019
 *      Author: jaros
 */

#ifndef ONEWIRE_H_
#define ONEWIRE_H_

#define OWDEV_FL_PRESENT		0x01
//#define OWDWV_FL_PRESENT		0x01

typedef struct
{
	uint8_t		romId[8];			// device ROM id
	uint32_t	timeStamp;			// last valid data in ms ticks, 0 if never
	int16_t		temperature;		// temperature * 100 in degC
	uint8_t		slotId;
	uint8_t		flags;				// OWDWV_FL_xxx
//	uint8_t 	errors;				// operation errors counter
	uint8_t		bitpos;				// bit counter for search operation
} owdev_data_t;

extern void owdev_Init();
extern void owdev_Service();

extern owdev_data_t *owdev_GetData(int idx);
extern owdev_data_t *owdev_GetDataById(uint8_t *id);

#endif /* ONEWIRE_H_ */


Další informace o konferenci Hw-list