標(biāo)題:
單片機(jī)GPIO模擬I2C 寫EEPROM延時(shí)問題
[打印本頁]
作者:
hxdby
時(shí)間:
2023-7-29 20:00
標(biāo)題:
單片機(jī)GPIO模擬I2C 寫EEPROM延時(shí)問題
大家好,
我用GPIO模擬I2C,和外部EEPROM通信,主要是單片機(jī)向EEPROM寫入數(shù)據(jù),寫入時(shí)規(guī)格書要求必須延時(shí)5ms.
我現(xiàn)在的程序延時(shí)用的是嘀嗒延時(shí),嘀嗒定時(shí)器延時(shí)應(yīng)該也是阻塞式延時(shí),我現(xiàn)在要做的就是消除程序里所有的阻塞式延時(shí),其他的延時(shí)已經(jīng)用定時(shí)器延改成了非阻塞了,就是這個(gè)寫EEPROM,我是怎么也沒想到比較好的非阻塞延時(shí)方式,如果用定時(shí)器來延時(shí),沒有好的思路。
部分代碼如下,
void Write_EEPROM(uint8_t address,uint8_t data,uint8_t paddr) //寫數(shù)據(jù)到EEPROM
{
IIC_GPIO_Start();
IIC_WriteOneByte(paddr);
IIC_WriteOneByte(address);
IIC_WriteOneByte(data);
IIC_GPIO_Stop();
Systick_delay_ms(5); //此處寫完后延時(shí)5ms,用的是阻塞式延時(shí),怎么改成非阻塞延時(shí)?
}
希望得到各位的幫助,謝謝
作者:
Hephaestus
時(shí)間:
2023-7-31 06:53
非阻塞就要把CPU控制權(quán)交給其他任務(wù)執(zhí)行,最簡(jiǎn)單的做法是上RTOS。
作者:
liyonghua111
時(shí)間:
2023-7-31 12:46
你可以使用一個(gè)狀態(tài)機(jī)和定時(shí)器中斷來實(shí)現(xiàn)非阻塞延時(shí)。在這種情況下,你需要將寫EEPROM的過程分解為幾個(gè)步驟,并為每個(gè)步驟定義一個(gè)狀態(tài)。然后,你可以在定時(shí)器中斷服務(wù)程序中改變狀態(tài)。
以下是一個(gè)簡(jiǎn)單的示例:
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) // 定時(shí)器中斷服務(wù)程序
{
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:
// 延時(shí)5ms后,返回到空閑狀態(tài)
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)
{
// 如果當(dāng)前狀態(tài)為空閑,則開始寫入過程
if (state == STATE_IDLE)
{
address = _address;
data = _data;
paddr = _paddr;
state = STATE_START;
}
}
這樣,你就可以在主循環(huán)中調(diào)用Write_EEPROM函數(shù),而不會(huì)阻塞其他任務(wù)。只有當(dāng)寫入過程完成(即狀態(tài)返回到STATE_IDLE)時(shí),才能開始新的寫入過程。
作者:
Y_G_G
時(shí)間:
2023-7-31 12:56
你選擇了模擬IIC,就注定了效率會(huì)變慢的
但這5mS是不需要這樣等待的
把等待低電平的部分重新寫一個(gè)函數(shù)
Write_EEPROM只管釋放SDA數(shù)據(jù)線和標(biāo)志一個(gè)標(biāo)志位,比如IIC_F,然后就函數(shù)返回
在主程序中增加一個(gè)一個(gè)檢測(cè)IIC_F的函數(shù)
進(jìn)入函數(shù)后,先:
if(IIC_F & !SDA)
{
IIC_F = 0;
其它處理;
}
只有收到應(yīng)答信號(hào)之后才進(jìn)行對(duì)應(yīng)的處理
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1