你可以使用一個狀態機和定時器中斷來實現非阻塞延時。在這種情況下,你需要將寫EEPROM的過程分解為幾個步驟,并為每個步驟定義一個狀態。然后,你可以在定時器中斷服務程序中改變狀態。
以下是一個簡單的示例:
c
typedef enum {
STATE_IDLE,
STATE_START,
STATE_WRITE_PADDR,
STATE_WRITE_ADDRESS,
STATE_WRITE_DATA,
STATE_STOP,
STATE_DELAY
} State;
volatile State state = STATE_IDLE;
uint8_t address, data, paddr;
void TIMx_IRQHandler(void) // 定時器中斷服務程序
{
if (TIM_GetITStatus(TIMx, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIMx, TIM_IT_Update);
switch (state)
{
case STATE_IDLE:
break;
case STATE_START:
IIC_GPIO_Start();
state = STATE_WRITE_PADDR;
break;
case STATE_WRITE_PADDR:
IIC_WriteOneByte(paddr);
state = STATE_WRITE_ADDRESS;
break;
case STATE_WRITE_ADDRESS:
IIC_WriteOneByte(address);
state = STATE_WRITE_DATA;
break;
case STATE_WRITE_DATA:
IIC_WriteOneByte(data);
state = STATE_STOP;
break;
case STATE_STOP:
IIC_GPIO_Stop();
state = STATE_DELAY;
break;
case STATE_DELAY:
// 延時5ms后,返回到空閑狀態
static int delayCounter = 0;
if (++delayCounter >= 5)
{
delayCounter = 0;
state = STATE_IDLE;
}
break;
}
}
}
void Write_EEPROM(uint8_t _address, uint8_t _data, uint8_t _paddr)
{
// 如果當前狀態為空閑,則開始寫入過程
if (state == STATE_IDLE)
{
address = _address;
data = _data;
paddr = _paddr;
state = STATE_START;
}
}
這樣,你就可以在主循環中調用Write_EEPROM函數,而不會阻塞其他任務。只有當寫入過程完成(即狀態返回到STATE_IDLE)時,才能開始新的寫入過程。 |