38
+ − 1 /**
+ − 2 ******************************************************************************
+ − 3 * @file uart.c
+ − 4 * @author heinrichs weikamp gmbh
+ − 5 * @version V0.0.1
+ − 6 * @date 27-March-2014
+ − 7 * @brief button control
+ − 8 *
+ − 9 @verbatim
+ − 10 ==============================================================================
+ − 11 ##### How to use #####
+ − 12 ==============================================================================
+ − 13 @endverbatim
+ − 14 ******************************************************************************
+ − 15 * @attention
+ − 16 *
+ − 17 * <h2><center>© COPYRIGHT(c) 2015 heinrichs weikamp</center></h2>
+ − 18 *
+ − 19 ******************************************************************************
+ − 20 */
+ − 21 /* Includes ------------------------------------------------------------------*/
+ − 22 #include "uart.h"
794
+ − 23 #include "uartProtocol_O2.h"
798
+ − 24 #include "uartProtocol_Co2.h"
662
+ − 25 #include "externalInterface.h"
+ − 26 #include "data_exchange.h"
704
+ − 27 #include <string.h> /* memset */
38
+ − 28
+ − 29 /* Private variables ---------------------------------------------------------*/
+ − 30
794
+ − 31
787
+ − 32
781
+ − 33 #define CHUNK_SIZE (25u) /* the DMA will handle chunk size transfers */
+ − 34 #define CHUNKS_PER_BUFFER (5u)
794
+ − 35
662
+ − 36 UART_HandleTypeDef huart1;
+ − 37
+ − 38 DMA_HandleTypeDef hdma_usart1_rx;
38
+ − 39
662
+ − 40 uint8_t rxBuffer[CHUNK_SIZE * CHUNKS_PER_BUFFER]; /* The complete buffer has a X * chunk size to allow fariations in buffer read time */
729
d646a0f724a7
Added auto detection functionality for sensors connected to the external interface:
Ideenmodellierer
diff
changeset
+ − 41 static uint8_t rxWriteIndex; /* Index of the data item which is analysed */
d646a0f724a7
Added auto detection functionality for sensors connected to the external interface:
Ideenmodellierer
diff
changeset
+ − 42 static uint8_t rxReadIndex; /* Index at which new data is stared */
d646a0f724a7
Added auto detection functionality for sensors connected to the external interface:
Ideenmodellierer
diff
changeset
+ − 43 static uint8_t lastCmdIndex; /* Index of last command which has not been completly received */
d646a0f724a7
Added auto detection functionality for sensors connected to the external interface:
Ideenmodellierer
diff
changeset
+ − 44 static uint8_t dmaActive; /* Indicator if DMA reception needs to be started */
794
+ − 45
798
+ − 46
742
+ − 47 static uint8_t SentinelConnected = 0; /* Binary indicator if a sensor is connected or not */
38
+ − 48
794
+ − 49
38
+ − 50 /* Exported functions --------------------------------------------------------*/
+ − 51
794
+ − 52
662
+ − 53 void MX_USART1_UART_Init(void)
38
+ − 54 {
662
+ − 55 /* regular init */
+ − 56
+ − 57 huart1.Instance = USART1;
704
+ − 58
+ − 59 if(externalInterface_GetUARTProtocol() == 0x04)
+ − 60 {
+ − 61 huart1.Init.BaudRate = 19200;
+ − 62 }
+ − 63 else
+ − 64 {
+ − 65 huart1.Init.BaudRate = 9600;
+ − 66 }
662
+ − 67 huart1.Init.WordLength = UART_WORDLENGTH_8B;
+ − 68 huart1.Init.StopBits = UART_STOPBITS_1;
+ − 69 huart1.Init.Parity = UART_PARITY_NONE;
+ − 70 huart1.Init.Mode = UART_MODE_TX_RX;
+ − 71 huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
+ − 72 huart1.Init.OverSampling = UART_OVERSAMPLING_16;
+ − 73
+ − 74 HAL_UART_Init(&huart1);
+ − 75
704
+ − 76 MX_USART1_DMA_Init();
+ − 77
787
+ − 78 memset(rxBuffer,BUFFER_NODATA,sizeof(rxBuffer));
662
+ − 79 rxReadIndex = 0;
+ − 80 lastCmdIndex = 0;
+ − 81 rxWriteIndex = 0;
+ − 82 dmaActive = 0;
794
+ − 83
742
+ − 84 SentinelConnected = 0;
794
+ − 85
662
+ − 86 }
38
+ − 87
662
+ − 88 void MX_USART1_UART_DeInit(void)
+ − 89 {
704
+ − 90 HAL_DMA_Abort(&hdma_usart1_rx);
662
+ − 91 HAL_DMA_DeInit(&hdma_usart1_rx);
+ − 92 HAL_UART_DeInit(&huart1);
+ − 93 }
+ − 94
+ − 95 void MX_USART1_DMA_Init()
+ − 96 {
+ − 97 /* DMA controller clock enable */
+ − 98 __DMA2_CLK_ENABLE();
+ − 99
+ − 100 /* Peripheral DMA init*/
+ − 101 hdma_usart1_rx.Instance = DMA2_Stream5;
+ − 102 hdma_usart1_rx.Init.Channel = DMA_CHANNEL_4;
+ − 103 hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; //DMA_MEMORY_TO_PERIPH;
+ − 104 hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
+ − 105 hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;
+ − 106 hdma_usart1_rx.Init.PeriphDataAlignment = DMA_MDATAALIGN_BYTE;
+ − 107 hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
+ − 108 hdma_usart1_rx.Init.Mode = DMA_NORMAL;
+ − 109 hdma_usart1_rx.Init.Priority = DMA_PRIORITY_LOW;
+ − 110 hdma_usart1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
+ − 111 HAL_DMA_Init(&hdma_usart1_rx);
+ − 112
+ − 113 __HAL_LINKDMA(&huart1,hdmarx,hdma_usart1_rx);
+ − 114
+ − 115 /* DMA interrupt init */
+ − 116 HAL_NVIC_SetPriority(DMA2_Stream5_IRQn, 0, 0);
+ − 117 HAL_NVIC_EnableIRQ(DMA2_Stream5_IRQn);
38
+ − 118 }
+ − 119
794
+ − 120 void UART_MUX_SelectAddress(uint8_t muxAddress)
779
+ − 121 {
+ − 122 uint8_t indexstr[4];
+ − 123
794
+ − 124 if(muxAddress <= MAX_MUX_CHANNEL)
779
+ − 125 {
794
+ − 126 indexstr[0] = '~';
+ − 127 indexstr[1] = muxAddress;
+ − 128 indexstr[2] = 0x0D;
+ − 129 indexstr[3] = 0x0A;
+ − 130
+ − 131 HAL_UART_Transmit(&huart1,indexstr,4,10);
779
+ − 132 }
+ − 133 }
+ − 134
794
+ − 135
+ − 136 void UART_SendCmdString(uint8_t *cmdString)
729
d646a0f724a7
Added auto detection functionality for sensors connected to the external interface:
Ideenmodellierer
diff
changeset
+ − 137 {
794
+ − 138 uint8_t cmdLength = strlen((char*)cmdString);
+ − 139
+ − 140 if(cmdLength < 20) /* A longer string is an indication for a missing 0 termination */
729
d646a0f724a7
Added auto detection functionality for sensors connected to the external interface:
Ideenmodellierer
diff
changeset
+ − 141 {
794
+ − 142 if(dmaActive == 0)
+ − 143 {
+ − 144 UART_StartDMA_Receiption();
+ − 145 }
+ − 146 HAL_UART_Transmit(&huart1,cmdString,cmdLength,10);
+ − 147 }
+ − 148 }
+ − 149
729
d646a0f724a7
Added auto detection functionality for sensors connected to the external interface:
Ideenmodellierer
diff
changeset
+ − 150
d646a0f724a7
Added auto detection functionality for sensors connected to the external interface:
Ideenmodellierer
diff
changeset
+ − 151 void StringToInt(char *pstr, uint32_t *puInt32)
d646a0f724a7
Added auto detection functionality for sensors connected to the external interface:
Ideenmodellierer
diff
changeset
+ − 152 {
d646a0f724a7
Added auto detection functionality for sensors connected to the external interface:
Ideenmodellierer
diff
changeset
+ − 153 uint8_t index = 0;
d646a0f724a7
Added auto detection functionality for sensors connected to the external interface:
Ideenmodellierer
diff
changeset
+ − 154 uint32_t result = 0;
d646a0f724a7
Added auto detection functionality for sensors connected to the external interface:
Ideenmodellierer
diff
changeset
+ − 155 while((pstr[index] >= '0') && (pstr[index] <= '9'))
d646a0f724a7
Added auto detection functionality for sensors connected to the external interface:
Ideenmodellierer
diff
changeset
+ − 156 {
d646a0f724a7
Added auto detection functionality for sensors connected to the external interface:
Ideenmodellierer
diff
changeset
+ − 157 result *=10;
d646a0f724a7
Added auto detection functionality for sensors connected to the external interface:
Ideenmodellierer
diff
changeset
+ − 158 result += pstr[index] - '0';
d646a0f724a7
Added auto detection functionality for sensors connected to the external interface:
Ideenmodellierer
diff
changeset
+ − 159 index++;
d646a0f724a7
Added auto detection functionality for sensors connected to the external interface:
Ideenmodellierer
diff
changeset
+ − 160 }
d646a0f724a7
Added auto detection functionality for sensors connected to the external interface:
Ideenmodellierer
diff
changeset
+ − 161 *puInt32 = result;
d646a0f724a7
Added auto detection functionality for sensors connected to the external interface:
Ideenmodellierer
diff
changeset
+ − 162 }
d646a0f724a7
Added auto detection functionality for sensors connected to the external interface:
Ideenmodellierer
diff
changeset
+ − 163
d646a0f724a7
Added auto detection functionality for sensors connected to the external interface:
Ideenmodellierer
diff
changeset
+ − 164 void StringToUInt64(char *pstr, uint64_t *puint64)
d646a0f724a7
Added auto detection functionality for sensors connected to the external interface:
Ideenmodellierer
diff
changeset
+ − 165 {
d646a0f724a7
Added auto detection functionality for sensors connected to the external interface:
Ideenmodellierer
diff
changeset
+ − 166 uint8_t index = 0;
d646a0f724a7
Added auto detection functionality for sensors connected to the external interface:
Ideenmodellierer
diff
changeset
+ − 167 uint64_t result = 0;
d646a0f724a7
Added auto detection functionality for sensors connected to the external interface:
Ideenmodellierer
diff
changeset
+ − 168 while((pstr[index] >= '0') && (pstr[index] <= '9'))
d646a0f724a7
Added auto detection functionality for sensors connected to the external interface:
Ideenmodellierer
diff
changeset
+ − 169 {
d646a0f724a7
Added auto detection functionality for sensors connected to the external interface:
Ideenmodellierer
diff
changeset
+ − 170 result *=10;
d646a0f724a7
Added auto detection functionality for sensors connected to the external interface:
Ideenmodellierer
diff
changeset
+ − 171 result += pstr[index] - '0';
d646a0f724a7
Added auto detection functionality for sensors connected to the external interface:
Ideenmodellierer
diff
changeset
+ − 172 index++;
d646a0f724a7
Added auto detection functionality for sensors connected to the external interface:
Ideenmodellierer
diff
changeset
+ − 173 }
d646a0f724a7
Added auto detection functionality for sensors connected to the external interface:
Ideenmodellierer
diff
changeset
+ − 174 *puint64 = result;
d646a0f724a7
Added auto detection functionality for sensors connected to the external interface:
Ideenmodellierer
diff
changeset
+ − 175 }
690
+ − 176 void ConvertByteToHexString(uint8_t byte, char* str)
+ − 177 {
+ − 178 uint8_t worker = 0;
+ − 179 uint8_t digit = 0;
+ − 180 uint8_t digitCnt = 1;
38
+ − 181
690
+ − 182 worker = byte;
+ − 183 while((worker!=0) && (digitCnt != 255))
+ − 184 {
+ − 185 digit = worker % 16;
+ − 186 if( digit < 10)
+ − 187 {
+ − 188 digit += '0';
+ − 189 }
+ − 190 else
+ − 191 {
+ − 192 digit += 'A' - 10;
+ − 193 }
+ − 194 str[digitCnt--]= digit;
+ − 195 worker = worker / 16;
+ − 196 }
+ − 197 }
662
+ − 198
742
+ − 199 void UART_StartDMA_Receiption()
+ − 200 {
798
+ − 201 if(dmaActive == 0)
742
+ − 202 {
798
+ − 203 if(HAL_OK == HAL_UART_Receive_DMA (&huart1, &rxBuffer[rxWriteIndex], CHUNK_SIZE))
+ − 204 {
+ − 205 dmaActive = 1;
+ − 206 }
742
+ − 207 }
+ − 208 }
690
+ − 209
798
+ − 210 void UART_ChangeBaudrate(uint32_t newBaudrate)
38
+ − 211 {
725
+ − 212
798
+ − 213 // HAL_DMA_Abort(&hdma_usart1_rx);
+ − 214 MX_USART1_UART_DeInit();
+ − 215 //HAL_UART_Abort(&huart1);
+ − 216 //HAL_DMA_DeInit(&hdma_usart1_rx);
+ − 217
+ − 218
+ − 219 // huart1.Instance->BRR = UART_BRR_SAMPLING8(HAL_RCC_GetPCLK2Freq()/2, newBaudrate);
+ − 220 huart1.Init.BaudRate = newBaudrate;
+ − 221 HAL_UART_Init(&huart1);
+ − 222 MX_USART1_DMA_Init();
+ − 223 if(dmaActive)
794
+ − 224 {
798
+ − 225 rxReadIndex = 0;
+ − 226 rxWriteIndex = 0;
+ − 227 dmaActive = 0;
742
+ − 228 UART_StartDMA_Receiption();
662
+ − 229 }
38
+ − 230 }
690
+ − 231
+ − 232 #ifdef ENABLE_SENTINEL_MODE
729
d646a0f724a7
Added auto detection functionality for sensors connected to the external interface:
Ideenmodellierer
diff
changeset
+ − 233 void UART_HandleSentinelData(void)
690
+ − 234 {
+ − 235 uint8_t localRX = rxReadIndex;
+ − 236 static uint8_t dataType = 0;
+ − 237 static uint32_t dataValue[3];
+ − 238 static uint8_t dataValueIdx = 0;
+ − 239 static receiveState_t rxState = RX_Ready;
+ − 240 static uint32_t lastReceiveTick = 0;
+ − 241 static uint8_t lastAlive = 0;
+ − 242 static uint8_t curAlive = 0;
+ − 243 static uint8_t checksum = 0;
742
+ − 244 static char checksum_str[]="00";
690
+ − 245
742
+ − 246 while((rxBuffer[localRX]!=0))
690
+ − 247 {
+ − 248 lastReceiveTick = HAL_GetTick();
+ − 249
+ − 250 switch(rxState)
+ − 251 {
+ − 252 case RX_Ready: if((rxBuffer[localRX] >= 'a') && (rxBuffer[localRX] <= 'z'))
+ − 253 {
+ − 254 rxState = RX_DetectStart;
+ − 255 curAlive = rxBuffer[localRX];
+ − 256 checksum = 0;
+ − 257 }
+ − 258 break;
+ − 259
+ − 260 case RX_DetectStart: checksum += rxBuffer[localRX];
+ − 261 if(rxBuffer[localRX] == '1')
+ − 262 {
+ − 263 rxState = RX_SelectData;
+ − 264 dataType = 0xFF;
+ − 265
+ − 266 }
+ − 267 else
+ − 268 {
+ − 269 rxState = RX_Ready;
+ − 270 }
+ − 271 break;
+ − 272
+ − 273 case RX_SelectData: checksum += rxBuffer[localRX];
+ − 274 switch(rxBuffer[localRX])
+ − 275 {
+ − 276 case 'T': dataType = rxBuffer[localRX];
+ − 277 break;
+ − 278 case '0': if(dataType != 0xff)
+ − 279 {
+ − 280 rxState = RX_Data0;
+ − 281 dataValueIdx = 0;
+ − 282 dataValue[0] = 0;
+ − 283
+ − 284 }
+ − 285 else
+ − 286 {
+ − 287 rxState = RX_Ready;
+ − 288 }
+ − 289 break;
+ − 290 default: rxState = RX_Ready;
+ − 291 }
+ − 292 break;
+ − 293
+ − 294 case RX_Data0:
+ − 295 case RX_Data1:
+ − 296 case RX_Data2:
+ − 297 case RX_Data4:
+ − 298 case RX_Data5:
+ − 299 case RX_Data6:
+ − 300 case RX_Data8:
+ − 301 case RX_Data9:
+ − 302 case RX_Data10: checksum += rxBuffer[localRX];
+ − 303 if((rxBuffer[localRX] >= '0') && (rxBuffer[localRX] <= '9'))
+ − 304 {
+ − 305 dataValue[dataValueIdx] = dataValue[dataValueIdx] * 10 + (rxBuffer[localRX] - '0');
+ − 306 rxState++;
+ − 307 }
+ − 308 else
+ − 309 {
+ − 310 rxState = RX_Ready;
+ − 311 }
+ − 312 break;
+ − 313
+ − 314 case RX_Data3:
+ − 315 case RX_Data7: checksum += rxBuffer[localRX];
+ − 316 if(rxBuffer[localRX] == '0')
+ − 317 {
+ − 318 rxState++;
+ − 319 dataValueIdx++;
+ − 320 dataValue[dataValueIdx] = 0;
+ − 321 }
+ − 322 else
+ − 323 {
+ − 324 rxState = RX_Ready;
+ − 325 }
+ − 326 break;
+ − 327 case RX_Data11: rxState = RX_DataComplete;
+ − 328 ConvertByteToHexString(checksum,checksum_str);
+ − 329 if(rxBuffer[localRX] == checksum_str[0])
+ − 330 {
+ − 331 rxState = RX_DataComplete;
+ − 332 }
+ − 333 else
+ − 334 {
+ − 335 rxState = RX_Ready;
+ − 336 }
+ − 337
+ − 338 break;
+ − 339
+ − 340 case RX_DataComplete: if(rxBuffer[localRX] == checksum_str[1])
+ − 341 {
+ − 342 setExternalInterfaceChannel(0,(float)(dataValue[0] / 10.0));
+ − 343 setExternalInterfaceChannel(1,(float)(dataValue[1] / 10.0));
+ − 344 setExternalInterfaceChannel(2,(float)(dataValue[2] / 10.0));
742
+ − 345 SentinelConnected = 1;
690
+ − 346 }
+ − 347 rxState = RX_Ready;
+ − 348 break;
+ − 349
+ − 350
+ − 351 default: rxState = RX_Ready;
+ − 352 break;
+ − 353
+ − 354 }
+ − 355 localRX++;
+ − 356 rxReadIndex++;
+ − 357 if(rxReadIndex >= CHUNK_SIZE * CHUNKS_PER_BUFFER)
+ − 358 {
+ − 359 localRX = 0;
+ − 360 rxReadIndex = 0;
+ − 361 }
+ − 362 }
+ − 363
+ − 364 if(time_elapsed_ms(lastReceiveTick,HAL_GetTick()) > 4000) /* check for communication timeout */
+ − 365 {
+ − 366 if(curAlive == lastAlive)
+ − 367 {
+ − 368 setExternalInterfaceChannel(0,0.0);
+ − 369 setExternalInterfaceChannel(1,0.0);
+ − 370 setExternalInterfaceChannel(2,0.0);
742
+ − 371 SentinelConnected = 0;
690
+ − 372 }
+ − 373 lastAlive = curAlive;
+ − 374 }
+ − 375
+ − 376 if((dmaActive == 0) && (externalInterface_isEnabledPower33())) /* Should never happen in normal operation => restart in case of communication error */
+ − 377 {
742
+ − 378 UART_StartDMA_Receiption();
690
+ − 379 }
+ − 380 }
+ − 381 #endif
38
+ − 382
729
d646a0f724a7
Added auto detection functionality for sensors connected to the external interface:
Ideenmodellierer
diff
changeset
+ − 383
798
+ − 384
742
+ − 385 uint8_t UART_isSentinelConnected()
+ − 386 {
+ − 387 return SentinelConnected;
+ − 388 }
729
d646a0f724a7
Added auto detection functionality for sensors connected to the external interface:
Ideenmodellierer
diff
changeset
+ − 389
662
+ − 390 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
38
+ − 391 {
662
+ − 392 if(huart == &huart1)
+ − 393 {
+ − 394 dmaActive = 0;
+ − 395 rxWriteIndex+=CHUNK_SIZE;
+ − 396 if(rxWriteIndex >= CHUNK_SIZE * CHUNKS_PER_BUFFER)
+ − 397 {
+ − 398 rxWriteIndex = 0;
+ − 399 }
787
+ − 400 if((rxWriteIndex / CHUNK_SIZE) != (rxReadIndex / CHUNK_SIZE) || (rxWriteIndex == rxReadIndex)) /* start next transfer if we did not catch up with read index */
662
+ − 401 {
787
+ − 402 if(externalInterface_GetUARTProtocol() != 0)
662
+ − 403 {
742
+ − 404 UART_StartDMA_Receiption();
662
+ − 405 }
+ − 406 }
+ − 407 }
38
+ − 408 }
+ − 409
794
+ − 410 void UART_ReadData(uint8_t sensorType)
+ − 411 {
+ − 412 uint8_t localRX = rxReadIndex;
38
+ − 413
794
+ − 414 while((rxBuffer[localRX]!=BUFFER_NODATA))
+ − 415 {
+ − 416 switch (sensorType)
+ − 417 {
+ − 418 case SENSOR_MUX:
+ − 419 case SENSOR_DIGO2: uartO2_ProcessData(rxBuffer[localRX]);
+ − 420 break;
798
+ − 421 #ifdef ENABLE_CO2_SUPPORT
+ − 422 case SENSOR_CO2: uartCo2_ProcessData(rxBuffer[localRX]);
794
+ − 423 break;
798
+ − 424 #endif
794
+ − 425 default:
+ − 426 break;
+ − 427 }
+ − 428
+ − 429 rxBuffer[localRX] = BUFFER_NODATA;
+ − 430 localRX++;
+ − 431 rxReadIndex++;
+ − 432 if(rxReadIndex >= CHUNK_SIZE * CHUNKS_PER_BUFFER)
+ − 433 {
+ − 434 localRX = 0;
+ − 435 rxReadIndex = 0;
+ − 436 }
+ − 437 }
+ − 438 }
+ − 439
+ − 440 void UART_FlushRxBuffer(void)
+ − 441 {
+ − 442 while(rxBuffer[rxReadIndex] != BUFFER_NODATA)
+ − 443 {
+ − 444 rxBuffer[rxReadIndex] = BUFFER_NODATA;
+ − 445 rxReadIndex++;
+ − 446 if(rxReadIndex >= CHUNK_SIZE * CHUNKS_PER_BUFFER)
+ − 447 {
+ − 448 rxReadIndex = 0;
+ − 449 }
+ − 450 }
+ − 451
+ − 452 }
662
+ − 453
38
+ − 454 /************************ (C) COPYRIGHT heinrichs weikamp *****END OF FILE****/