Uart ve I2C Birlikte Çalışma Problemi

Başlatan sımışka, 13 Temmuz 2020, 14:58:22

sımışka

Merhaba,

Öncelikle kullandığım mikrodenetleyici stm32f103 ve Hal kütüphanesi.

Elimde şu an kod yok daha sonra ekleyeceğim ama sözlü anlatmak gerekirse,
Uart receive interrupt ile bir dizi data alıyorum 1er byte şeklinde toplamda 7 byte veri okuyorum host uygulamadan, aldığım dataları callback funksiyonu içerisinde bir kaç flag setliyorum veya birkaç değişkenin değerini , okuduğum değer ile setliyorum ve ardında 35 byte kadar hosta veri aktarıyorum. Bu 35 byte içerisinde bir kaç input ve output durumu ve dış kesme ile 2 farklı kanalın o anlık değerleri.Günlerce banamısın demeden çalışıyor. Buraya kadar sorun yok.
 
Ardından i2c ile haberleşen adc entegresini aktif ettim, bir kaç hal i2c fonksiyonu kullanıp datayı okuyorum ardından sprintf ile float olarak bir diziye yazıyorum. Bu dizinin 2 bytenıda hosta gönderdiğim 35 byte içerisinde ilgili yerlerine ekliyorum. RX ledim devamlı yanıp sönüyor donanımsal olarak data gelmeye devam ediyor aslında ama bir süre sonra TX ledim artık tamamen sönüyor, data kaçırmaya başlıyorum ve hiç data alamamaya başlıyorum. Stm Studio da gelen buffer ı anlık izliyorum, hiç bir değişim olmamaya başlıyor ve buffer içerisi sıfırlanıyor. Dolayısı ile veri basamıyorum artık. Dinamik bellek alımı vb. işlem yapmıyorum herşey statik.

Kod olmadan fikir yürütecek olursak, neden olabilir acaba ?
 


sımışka

#1
i2c ile şu şekilde data okuyorum geri dönüşlerini kontrol ediyorum.

HAL_I2C_IsDeviceReady(pI2CHandle,(MCP3424add<<1),1,10)
HAL_I2C_Mem_Read(pI2CHandle,(MCP3424add<<1),configSet,1,ADCdatarec,5,10);
//HAL_I2C_Master_Receive(pI2CHandle,(MCP3424add<<1),ADCdatarec,5,10);

ADCval=(ADCdatarec[2]<<0)|(ADCdatarec[1]<<8)|(ADCdatarec[0]<<16
ADCval = (0x20000&ADCval ? (int)(0x1FFFF&ADCval)-0x20000 : ADCval);
Bu fonksiyonlar polling mode da çalışıyor. Her fonksiyonun timeout değeri 10ms olarak ayarladım, uarttan bana her sorgu 100ms de bir geliyor. 3 fonksiyonda timeout süresinin bitmesine kadar bloklu bir şekilde kalsa bile kurtarıyor olmasını beklerim. Sorunu yanlış yerde mi arıyorum acaba ?

sımışka

Denediğim kodumu paylaşıyorum. Normalde i2c ile işlemler yaptığım mcp3424 fonksiyonunu kapattığımda hiç bir sorun yaşamıyorum. Uzun süre boyunca veri alıp gönderiyor. Fakat i2c ile işlem yaptığım fonksiyonu açtığımda bir süre sonra örneğin 15 dk sonra uartrxcallback fonksiyonuna girmiyor. Girip girmediğini  counterFlag değişkeni ile stm studio dan anlık izleyerek anlıyorum. Reset butonu ile resetlediğimde tekrar çalışmaya başlıyor. Yardımcı olabilir misiniz ? sprintf fonksiyonundan şüpheleniyorum.

void setConfiguration(CHANNELS channel,RESOLUTION resolution,MEASURE_MODE mode,PGA pga)
{

	configSet |= (channel & 0x3) << 5;
	configSet |= (mode & 0x1) << 4;
	configSet |= (resolution & 0x3) << 2;
	configSet |= pga & 0x3;
	HAL_I2C_Mem_Read(&hi2c1,(MCP3424add<<1),configSet,1,ADCdatarec,5,10);
}

void MCP3424(){

	  if(HAL_I2C_IsDeviceReady(&hi2c1,(MCP3424add<<1),1,10)==HAL_OK){
//		  if(HAL_I2C_Mem_Read(&hi2c1,(MCP3424add<<1),configSet,1,ADCdatarec,5,10)==HAL_OK)
//		  {
//			  HAL_I2C_Master_Receive(&hi2c1,(MCP3424add<<1),ADCdatarec,5,10);
//		  	  HAL_Delay(5);
//		  }
		  HAL_I2C_Master_Receive(&hi2c1,(MCP3424add<<1),ADCdatarec,5,10);
	  	  HAL_Delay(5);
	  }
	  ADCval=(ADCdatarec[2])|(ADCdatarec[1]<<8)|(ADCdatarec[0]<<16);
	  ADCval = (0x20000&ADCval ? (uint32_t)(0x1FFFF&ADCval)-0x20000 : ADCval);

	  //volt=(float)((ADCval/131071.0)*(2.048)*(180/33.0));
	  //volt=(float)((((ADCval/131071.0)*((2.048*180.0)/33.0))/249.0)*1000.0);
	  volt=(float)((((2048.0)/(131071.0/ADCval))*((4.0)/204.0)));
	  sprintf(msgOut,"%.2f\n\r", volt);

	  if((msgOut[1])!=46) // çift haneli akım
	  {
		  a=((msgOut[4]-'0')+((msgOut[3]-'0')*10));
		  b=(msgOut[1]-'0')+((msgOut[0]-'0')*10);
		  if(b==0 && a<50)
		  {
		  	  msg[20]=0;
		  	  msg[21]=0;
		  }
		  else
		  {
			  msg[20]=(a & 0x000000ff);
			  msg[21]=(b & 0x000000ff);
		  }
	  }
	  else
	  {
		  a=(msgOut[3]-'0')+((msgOut[2]-'0')*10);
		  b=msgOut[0]-'0';

		  if(b==0 && a<50)
		  {
		  	  msg[20]=0;
		  	  msg[21]=0;
		  }
		  else
		  {
			  msg[20]=(a & 0x000000ff);
			  msg[21]=(b & 0x000000ff);
		  }
	  }
}

uint32_t counterFlag=0;
/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  /* Prevent unused argument(s) compilation warning */
	counterFlag++;
	if(rxIndex==0)
	{
		for(int i=0;i<UART0_RXBufferSize;i++)
			rxBuffer[i]=0;
	}
	if (rxData!=0x23)
		rxBuffer[rxIndex++]=rxData;
	else
	{
		rxIndex=0;
		if(rxBuffer[0]==0x7E && rxBuffer[1]==0x01 && rxBuffer[2]==0x01 && rxBuffer[3]==0xAA && rxBuffer[4]==0x02)
		{
			HAL_UART_Transmit(&huart1, (uint8_t*)msg, sizeof(msg),100);
		}
		else
		{
		 if(rxBuffer[0]==0x7E && rxBuffer[1]==0x02 && rxBuffer[3]==MESSAGE_OPENCLOSE && (rxBuffer[2]!=0x05 && rxBuffer[2]!=0x06))
		 {
			if(rxBuffer[2]==0x01)
			{
				if(rxBuffer[5]==0x00)
					hsc0_OpenStatus=0;
				else
					hsc0_OpenStatus=1;
			}
			if(rxBuffer[2]==0x02)
			{
				if(rxBuffer[5]==0x00)
					hsc1_OpenStatus=0;
				else
					hsc1_OpenStatus=1;
			}
			if(rxBuffer[2]==0x03)
			{
				if(rxBuffer[5]==0x00)
					hsc2_OpenStatus=0;
				else
					hsc2_OpenStatus=1;
			}
			if(rxBuffer[2]==0x04)
			{
				if(rxBuffer[5]==0x00)
					hsc3_OpenStatus=0;
				else
					hsc3_OpenStatus=1;
			}
		}
		else if(rxBuffer[0]==0x7E && rxBuffer[1]==0x02 && rxBuffer[3]==MESSAGE_VALUESET && (rxBuffer[2]!=0x05 && rxBuffer[2]!=0x06))
		{
			if(rxBuffer[2]==0x01)
				HSC0_TOTAL = rxBuffer[5]<<24 | rxBuffer[6]<<16 | rxBuffer[7]<<8 | rxBuffer[8];
			if(rxBuffer[2]==0x02)
				HSC1_TOTAL = rxBuffer[5]<<24 | rxBuffer[6]<<16 | rxBuffer[7]<<8 | rxBuffer[8];
			if(rxBuffer[2]==0x03)
				HSC2_TOTAL = rxBuffer[5]<<24 | rxBuffer[6]<<16 | rxBuffer[7]<<8 | rxBuffer[8];
			if(rxBuffer[2]==0x04)
				HSC3_TOTAL = rxBuffer[5]<<24 | rxBuffer[6]<<16 | rxBuffer[7]<<8 | rxBuffer[8];
		}
		else if(rxBuffer[0]==0x7E && rxBuffer[1]==0x02 && rxBuffer[2]==0x05) // digital cıkıs
		{
			digitalOutputFlag=1;
		 if(rxBuffer[3]==0xFF)
		 {
			 if(rxBuffer[5]==0x01)
			 {
				 msg[18]=0xff;
			 }
			 else if (rxBuffer[5]==0x00)
			 {
				 msg[18]=0x00;
			 }
		   }
		 else
		 {
			  msg[18]=rxBuffer[3];
		 }

		}
		else if(rxBuffer[0]==0x7E && rxBuffer[1]==0x02 && rxBuffer[2]==0x06)
		{
			relayFlag=1;
		 if(rxBuffer[3]==0x03)
		 {
				if(rxBuffer[5]==0x01)
				{
					retValR1=1;
					retValR2=1;
					msg[19]=0x03;
				}
				else
				{
					retValR1=0;
					retValR2=0;
					msg[19]=0x00;
				}
		 }
		 else
		 {
			 msg[19]=rxBuffer[3];
			if(rxBuffer[3]==0x01)
			{
					retValR1=1;
					retValR2=0;
			}
			else if(rxBuffer[3] == 0x02)
			{
					retValR2=1;
					retValR1=0;
			}
		  }
		}
		else{
			for(int i=0;i<UART0_RXBufferSize;i++)
				rxBuffer[i]=0;
		}
	  }
	}

	HAL_UART_Receive_IT(&huart1, &rxData, 1);//one car
}


main içerisinde ;

  
  HAL_UART_Receive_IT(&huart1, &rxData,1);
  setConfiguration(3,RESOLUTION_18_BITS,CONTINUOUS_MODE,PGA_X1);

while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */

	  readInputStatus();
	  dataFilling();
	  if(relayFlag)
	  {
		  relayFlag=0;
		  if(retValR1)
			  HAL_GPIO_WritePin(GPIOA, RELAY1_Pin, GPIO_PIN_RESET);
		  else
			  HAL_GPIO_WritePin(GPIOA, RELAY1_Pin, GPIO_PIN_SET);
		  if(retValR2)
			  HAL_GPIO_WritePin(GPIOA, RELAY2_Pin, GPIO_PIN_RESET);
		  else
			  HAL_GPIO_WritePin(GPIOA, RELAY2_Pin, GPIO_PIN_SET);
	  }

	  //HAL_I2C_Master_Transmit(&hi2c1,mcp4725_address,buffer,3,100);
	  if(digitalOutputFlag)
	  {
		  digitalOutputFlag=0;
		  HAL_I2C_Master_Transmit(&hi2c1,digitalOutputsAddr,&digitalOutputs,1,1000);
	  }
	  if(c>5000)
	  {
		  c=0;
		  MCP3424();
	  }
	  c++;
  }



sımışka

Çözüm:

void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{

__HAL_UART_CLEAR_PEFLAG(&huart1);
__HAL_UART_CLEAR_OREFLAG(&huart1);
__HAL_UART_CLEAR_NEFLAG(&huart1);
__HAL_UART_CLEAR_FEFLAG(&huart1);
__HAL_UART_DISABLE_IT(&huart1, UART_IT_ERR);

HAL_UART_Receive_IT(&huart1, &rxData, 1);

}