скрытое меню

UART

фотка 1

115200 макс скорость, пакет макс 9бит (отклонение макс. частоты приемника / передатчика 10%)

Аппаратный контроль CTS / RTS

CTS - (Clear to send) - вход для разрешения Передатчику посылать данные. Передатчик ждет для передачи CTS = 0.
RTS Request to send - запрос COM-порта на передачу данных (сигнал COM-порта о готовности принимать данные).

Data terminal ready - сигнал готовности COM-порта к обмену данными.
Data set ready - вход сигнала готовности от подключённого к порту устройства.

STM32407VE** (тренируемся - все на одной плате)

фотка 2

Желтый и черный это RTS-CTS, CTS-RTS
зеленый и синий Tx-Rx, Rx-Tx

Для простоты - USART3 только передача, USART2 только прием

используем прерывания (очень не простой для понимания алгоритм, но для быстродействия - самый подходящий вариант)

Не скрою убито 2 дня. Поиски в интернете как ни странно не много дают. Помог на удивление yuotube.
Главное:
1. HAL_UART_Receive_IT и HAL_UART_Transmit_IT - это всего лишь команда к активации режима прерываний!
2. HAL_UART_Receive_IT(&huart2, (uint8_t *)receiveBuffer, 1) ставим до передачи и в обработчике прерывания HAL_UART_RxCpltCallback после приема данных ОПЯТЬ активируем HAL_UART_Receive_IT (т.к. он почему-то скидывается)
3. Почему-то прием идет всегда по 1 байту.
4. Полезно использовать HAL_UART_ErrorCallback , туда залетают полезные по информативности проблемы - переполнение и др.

В общем простой пример такой:


uint8_t transmitBuffer[32];
uint8_t receiveBuffer[2]; // принимаем все-равно по 1 байту
__IO ITStatus RxEnd = 0;
__IO ITStatus TxEnd = 0;
uint16_t RxWaitingNumber=0;
uint8_t Rx_Buffer[100];
uint8_t Rx_indx=0;

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
	uint16_t count=huart->RxXferCount;
	uint16_t size=huart->TxXferSize;

	if (huart-> Instance == USART3) 
	{
		printf("\n!!! --> USART3 HAL_UART_TxCpltCallback count=%d  size=%d \n",count,size);
		TxEnd=1;
	}	
	else if (huart-> Instance == USART2) 
	{
		printf("\n!!! --> USART2 HAL_UART_TxCpltCallback count=%d  size=%d \n",count,size);
	}	
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if (huart-> Instance == USART2 )
	{
		if(Rx_indx==0)
			for(int ii=0;ii<100;ii++)
				Rx_Buffer[ii]=0;

		uint16_t count=huart->RxXferCount;
		uint16_t size=huart->RxXferSize;
		Rx_Buffer[Rx_indx]=receiveBuffer[0];
		printf("\n! <- size=%d count=%d(HAL_UART_RxCpltCallback) '%c' \n",size,count,receiveBuffer[0]);
		
		if(Rx_indx>=(RxWaitingNumber-1)) //приняли ожидаемое количество байт
			RxEnd=1; // и НЕ активируем прерывание для приема других байт
		else
		{
			Rx_indx++;
			HAL_UART_Receive_IT(&huart2, (uint8_t *)receiveBuffer, 1); // ОБЯЗАТЕЛЬНО активизируем прерывание заново для приема осташихся (ожидаемых) байт
		}
	} 
	else if (huart-> Instance == USART3) 
	{
		printf("USART3\n"); 
	}	
}

int main(void)
.....
	__HAL_UART_FLUSH_DRREGISTER (&huart2);
	__HAL_UART_FLUSH_DRREGISTER (&huart3);

	Rx_indx=0; // устанавливаем счетчик принятых байт на 0
	RxWaitingNumber=10; // устанавливаем количество ожидаемых байт, отлавливаем завершение по RxEnd==1
	HAL_UART_Receive_IT(&huart2, (uint8_t *)receiveBuffer, 1); // активируем прерывания по приходу каждого байта
	HAL_UART_Transmit_IT(&huart3, (uint8_t*)transmitBuffer,10);

	/*while(TxEnd==0) // ждем окончания передачи всех байт 
			printf(".");*/

	while(RxEnd==0) // ждем окончания приема 10 байт (сколько послали , столько и должно вернуться)
			printf(".");

	printf("\n<--- result : received 10 bytes %s \n ",(uint8_t *)Rx_Buffer);
	// из непонятого receiveBuffer тут указывет на receiveBuffer[9]

полный проект Keil(STM32CubeMx) можно скачать здесь

Передача в режиме блокировки

Самое простое (что приходит в голову)- использовать blocking mode HAL_UART_Transmit(...,timeout) и HAL_UART_Receive(...,timeout), [прерывания отключены]. Это , когда посылая пакет байт устанавливаем таймаут и ждем результат тупо блокирую продолжение программы. Далее в таком же стиле принимаем байты.


// Если 2 USART на одной плате , допустим с huart3 передаем, а на huart2 пытаемся принять :
status=HAL_UART_Transmit(&huart3, (uint8_t*)transmitBuffer,10,1000);

while (1)
{
    HAL_Delay(500);       
    status=HAL_UART_Receive(&huart2, (uint8_t *)receiveBuffer, 10,500); // блокирует передачу (незаконченную ) !? 
    // хотелось принять 10байт (реально принимаем 1), при этом status=3 (тайм-аут)
    // если принимать именно 1 байт (а не 10), то status будет=0 (без ошибок)

включаем на передачу - DMA

Тут прерывание используется (без вариантов). Но прерывание именно DMA!


status=HAL_UART_Transmit_DMA(&huart3, (uint8_t*)transmitBuffer,10);
while (1)
{
    HAL_Delay(500);       
    status=HAL_UART_Receive(&huart2, (uint8_t *)receiveBuffer, 10,500); // опять блокирует передачу 
    // и мы принимаем только 1 байт (а хотелось 10)

USART_FLAG_CTS – обнаружены входные данные с помощью линии CTS (для синхронного режима)
USART_FLAG_LBD – обнаружен разрыв
USART_FLAG_TXE – регистр передачи данных пуст
USART_FLAG_TC – передача окончена
USART_FLAG_RXNE – приняты данные
USART_FLAG_IDLE – линия свободна
USART_FLAG_ORE – переполнение
USART_FLAG_NE – ошибка принятых данных (шум в принимаемом кадре)
USART_FLAG_FE – ошибка кадров (первый стоп-бит = 0)
USART_FLAG_PE – ошибка чётности