-
-
Save skakri/4ec0abe7f7088c21486008f577970342 to your computer and use it in GitHub Desktop.
i2c slave with PMS150C
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define I2C_SLAVE_ADDRESS (0xA0 >> 1) | |
#define BUF_SIZE 16 | |
enum { | |
IDLE, | |
START, | |
STOP, | |
ADDR, | |
OP, | |
READDATA, | |
WRITEDATA, | |
IACK1, | |
IACK2, | |
WACK1, | |
WACK2, | |
RACK | |
}; | |
enum { | |
LOW, | |
HIGH | |
}; | |
enum { | |
INPUT, | |
OUTPUT | |
}; | |
sda equ PA.4; | |
scl equ PA.3; | |
sdac equ PAC.4; | |
sclc equ PAC.3; | |
BYTE last, current; | |
BYTE sda_change, scl_change; | |
BYTE state; | |
BYTE data; | |
BYTE len; | |
BYTE buf[BUF_SIZE]; | |
WORD ptr; | |
BYTE wrt; | |
BYTE pause_sda; | |
void clear_sda() | |
{ | |
pause_sda = 1; | |
sdac = OUTPUT; | |
sda = LOW; | |
} | |
void release_sda() | |
{ | |
pause_sda = 0; | |
sdac = INPUT; | |
sda = HIGH; | |
} | |
void sda_low() | |
{ | |
pause_sda = 1; | |
sdac = OUTPUT; | |
sda = LOW; | |
} | |
void sda_high() | |
{ | |
pause_sda = 1; | |
sdac = INPUT; | |
sda = HIGH; | |
} | |
void check_scl() | |
{ | |
if (scl == HIGH) { | |
switch(state) { | |
case ADDR: | |
if (sda) | |
data = (data << 1) | 1; | |
else | |
data = (data << 1); | |
len++; | |
if (len < 7) | |
break; | |
if (data != I2C_SLAVE_ADDRESS) | |
state = IDLE; | |
else | |
state = OP; | |
break; | |
case OP: | |
//读完7位地址位,剩1位读写位 | |
if (sda) | |
data = 1; | |
else | |
data = 0; | |
state = IACK1; | |
break; | |
case IACK1: | |
state = IACK2; | |
break; | |
case WRITEDATA: | |
if (sda) | |
data = (data << 1) | 1; | |
else | |
data = (data << 1); | |
len++; | |
if (len < 8) | |
break; | |
len = 0; | |
*ptr = data; | |
ptr++; | |
data = 0; | |
state = WACK1; | |
break; | |
case WACK1: | |
state = WACK2; | |
break; | |
case READDATA: | |
if (len < 8) | |
break; | |
ptr++; | |
data = *ptr; | |
len = 0; | |
state = RACK; | |
break; | |
case RACK: | |
if (sda == HIGH) | |
state = IDLE; | |
else | |
state = READDATA; | |
break; | |
default: | |
break; | |
} | |
} else { | |
switch(state) { | |
case IACK1: | |
clear_sda(); | |
break; | |
case IACK2: | |
release_sda(); | |
if (data == 0) { | |
len = 0; | |
ptr = buf; | |
state = WRITEDATA; | |
wrt = 1; | |
} else { | |
state = READDATA; | |
wrt = 0; | |
ptr = buf; ptr++; //指向data0 | |
len = 1; | |
//make sda high/low | |
data = *ptr; | |
if (data.7) { | |
sda_high(); | |
} else { | |
sda_low(); | |
} | |
data <<= 1; | |
} | |
break; | |
case WACK1: | |
clear_sda(); | |
break; | |
case WACK2: | |
release_sda(); | |
state = WRITEDATA; | |
break; | |
case READDATA: | |
//make sda high low | |
if (data.7) { | |
sda_high(); | |
} else { | |
sda_low(); | |
} | |
data <<= 1; | |
len++; | |
break; | |
case RACK: | |
release_sda(); | |
break; | |
default: | |
break; | |
} | |
} | |
} | |
void check_sda() | |
{ | |
//pms150c主动操作sda的时候,不检查sda是否跳变 | |
if (pause_sda) | |
return; | |
if (scl == HIGH && !scl_change) { | |
if (sda == HIGH) { | |
//scl高电平,sda跳成高电平,是STOP信号 | |
state = IDLE; | |
if (wrt) { | |
//write done | |
} else { | |
//read done | |
} | |
len = 0; | |
ptr = buf; | |
data = 0; | |
} else { | |
//scl高电平,sda跳成高电平,是START信号 | |
//状态机转成准备接收地址的状态 | |
state = ADDR; | |
len = 0; | |
ptr = buf; | |
data = 0; | |
} | |
} | |
} | |
void i2c_init() | |
{ | |
//设置所有pin为输入 | |
PAC = 0; | |
//sda scl加上弱上拉 | |
PAPH = _FIELD(sda, scl); | |
state = IDLE; | |
data = 0; | |
len = 0; | |
ptr = buf; | |
pause_sda = 0; | |
current = PA; | |
last = current; | |
} | |
void FPPA0 (void) | |
{ | |
.ADJUST_IC SYSCLK=IHRC/2, IHRC=16MHz, VDD=5V; | |
// WatchDog Disable, RAM 0 ~ 0xF temporary be used | |
// You can add the follow code : | |
// CLKMD.En_WatchDog = 1; // WatchDog Enable | |
i2c_init(); | |
while (1) | |
{ | |
//读取 | |
current = PA; | |
sda_change = (last ^ current) & _FIELD(sda); | |
scl_change = (last ^ current) & _FIELD(scl); | |
last = current; | |
if (scl_change) | |
check_scl(); | |
if (sda_change) | |
check_sda(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment