I need to connect many sensors to master MCU, so MPCM one-wire USART is my choice.
There is a bug , I can't find out the reason: the 9th bit is set every time.
Anyone can find the bug in the code?
init:
void USART0_oneWireInit(void) {
PORTB.DIRCLR = PIN2_bm; //default USART.TxD = PB2
USART0.BAUD = (uint16_t)USART0_BAUD_RATE(9600);
USART0.CTRLA |= (USART_LBME_bm | USART_RXCIE_bm);
USART0.CTRLB = 1 << USART_MPCM_bp // Multi-processor Communication Mode: enabled
| 1 << USART_ODME_bp // Open Drain Mode Enable: disabled
| USART_RXMODE_CLK2X_gc // CLK2x mode
| 1 << USART_SFDEN_bp // Start Frame Detection Enable: enabled
| 1 << USART_TXEN_bp // Transmitter Enable: enabled
| 1 << USART_RXEN_bp; // Reciever enable: enabledUSART0.CTRLC =
USART_CHSIZE_9BITH_gc // Character size: 9 bit read high byte first
| USART_PMODE_EVEN_gc ; // Even Parity}
RXC interrupt handler:
ISR(USART0_RXC_vect){
uint8_t rxDataH = USART0.RXDATAH;
uint8_t rxDataL = USART0.RXDATAL;
switch(uartStatus){
case uartSending:
if(rxDataL == charToSend){
sendingStatus = uartSendOK;
}else{
sendingStatus = uartSendCONFLICT;
}
return;
case uartReceiveIdle: //address frame
//uartRcvPush(rxDataL,rxDataH); return;
if( !(rxDataH & 0x06) && (rxDataH & 1)){ //FERR=0 PERR=0 adress frame
if((rxDataL == sensorID)||(rxDataL == 0xFF)){
DISABLE_MPCM;
uartStatus = uartReceiving;
uartRcvPush(rxDataL,true);
return;
}
}
break;
case uartReceiving: //data frame process
//uartRcvPush(rxDataL,rxDataH); return;
if(!(rxDataH & 0x07)){ //FERR==0 and PERR==0 and 9th bit==0
uartRcvPush(rxDataL,false);
return;
}
if(rxDataH & 0x06)
return; //FERR=1 or PERR=1 ,just throw it
else
if((rxDataH & 1)){ //FERR=0 PERR=0 adress frame
if((rxDataL == sensorID)||(rxDataL == 0xFF)){ //continue to send
uartRcvPush(rxDataL,true);
}else{ //send to other
ENABLE_MPCM;
uartStatus = uartReceiveIdle;
}
}
return;
default:return;
}
}
send code:
uartSendStatus_t USART0_oneWireSend(void){
uartStatus = uartSending;
PORTB.DIRSET = PIN2_bm; // pb2 pin must be output to transmit
for(uint8_t i = 0; i <= uartDataIdx; i++){
charToSend = uartDataToSend[i].data;
while (!(USART0.STATUS & USART_DREIF_bm)){;}
if(uartDataToSend[i].addressBit)
USART0.TXDATAH |= 1;else
USART0.TXDATAH &= 0xFE;
USART0.TXDATAL = charToSend;
sendingStatus = uartSendSENDING;
while(sendingStatus == uartSendSENDING){ //need to check if timeout
}if(sendingStatus != uartSendOK){
break;
}
}
PORTB.DIRCLR = PIN2_bm;
uartStatus = uartReceiveIdle;
return sendingStatus;
}
In the send function, I set the 9th bit for every byte, only 1st address byte was set with 1, all other byte is 0.
But, with loop back check, what RxD received is always RXDATAH = 0x81 & RXDATAL = what sent on TxD.
And I checked the other receiver(sensors), what they received is same as upper.
That means the 9th bit was set to 1 before sent out.
Where is the bug?