Цитата
Если софтовый Уарт должен одновременно передавать и принимать
Набросал как в первом приближении (без подкалибровывания VLO и с низким разрешением) это могло бы выглядеть:
Код
typedef unsigned int CPU_Time_t;
CPU_Time_t CPU_Time(void){
return TAR;
}
CPU_Time_t CPU_Elapsed(CPU_Time_t ts){
return (CPU_Time() - ts);
}
int SW_UART_Rx_Byte(void){
static CPU_Time_t ts;
static int st;
static unsigned char mask;
static unsigned char Rx_byte;
int rc = -1;
switch(st)
case 0:
if(START_DETECT()){
ts = CPU_Time(); st++;
}
break;
case 1:
if(CPU_Elapsed(ts) > CPU_uS(HALF_BIT_TIME_uS)){
if(START_PIN_GET() == 0){
ts = CPU_Time(); st++; // valid START received
mask = 0x01; Rx_byte = 0;
}else{
st = 0;
}
}
break;
case 2:
if(CPU_Elapsed(ts) > CPU_uS(BIT_TIME_uS)){
ts = CPU_Time();
if(Rx_PIN_State_GET()) Rx_byte |= mask;
mask <<= 1;
if(!(mask & 0xFF)) st++; // 8 bits received
}
break;
case 3:
if(CPU_Elapsed(ts) > CPU_uS(BIT_TIME_uS)){
if(Rx_PIN_State_GET()) rc = Rx_byte; // valid STOP received
st = 0;
}
break;
}
return rc;
}
int SW_UART_Tx_Byte(int Tx_Byte){
static CPU_Time_t ts;
static int st;
static unsigned char mask;
static unsigned char Tx_tmp;
int rc = -1;
if(TxByte & 0xFF00){// Tx break
st = 0;
return TxByte;
}
switch (st){
case 0:
Tx_tmp = Tx_Byte; mask = 0x01;
TX_OUT_DOWN(); // START post
ts = CPU_Time();
st++;
break;
case 1:
if(CPU_Elapsed(ts) > CPU_uS(BIT_TIME_uS)){
ts = CPU_Time();
if(Tx_tmp & mask) TX_OUT_UP();
else TX_OUT_DOWN();
mask <<= 1;
if(!(mask & 0xFF)) st++; // 8 bits post
}
break;
case 2:
if(CPU_Elapsed(ts) > CPU_uS(BIT_TIME_uS)){
ts = CPU_Time();
TX_OUT_UP(); // STOP post
st++;
}
break;
case 3:
if(CPU_Elapsed(ts) > CPU_uS(BIT_TIME_uS)){// end of STOP-bit
rc = Tx_tmp;
st = 0;
}
break;
}
return(rc);
}
void echo(void){
static int st;
static int ch;
int rx_tmp;
rx_tmp = SW_UART_Rx_Byte();
switch (st){
case 0:
ch = rx_tmp;
if( ch & 0xFF00) break;
st++;
case 1:
if(SW_UART_Tx_Byte(ch) != ch) break;
st = 0;
}
}
Такое для низких скоростей и небольшой загрузки могло бы прокатить