Jump to content
xrou

Как сделать прием пакета неизвестной длины по UART

Recommended Posts

Здравствуйте, пытаюсь обрабатывать пакеты приходящие от ESP8266 (01), но проблема в том, что пакеты всегда разной длины ведь мы не знаем, что напишет пользователь (хотя даже ответы на AT команды всегда разной длины). Знаю, что в плате F0 есть прерывание по символу, но у меня F103C8T6. Как быть? Создать массив большого размера нельзя, т.к. HAL_Recieve_IT ждет пока не наберется нужное кол-во символов.

Приму любую идею и советы

Share this post


Link to post
Share on other sites

а зачем тебе знать длину пакета? Процесс приема по уарт довольно медленный, если на скоростях до 115200. Я при работе с 8266 использовал двухсимвольный буфер с приемом по дма и прерыванием по полубуферу.

Дальше просто производится парсинг посимвольный и инкрементное формирование строки программой. Окончание строки - маркер символ. Как правило \n

Если вообще обмен медленный (ну скажем 9600 бод) можно вообще односимвольный буфер юзать. Скопировать в прерывании ты успеешь. Но с ДМА приятнее и можно использовать скорости порядка 3,5 мегабит. Это конечно не стандарт, но 8266 вывозит. Вопрос только надо ли оно такое быстрое? Я при использовании уарта всегда стараюсь подобрать или рассчитать минимально возможную скорость обмена для комфортного выполнения задачи. Так все становится намного проще и стабильнее

вот код для работы с односимвольным буфером. Посмотри для примерчика. Тут работа по уарт с терминалом на компе. Командами с консоли конфигурируются центральные часы респределенной системы управления. Простенькая поделка где пакет неизвестной длинны, но ограничен определенной максимальной, длиннее которой быть не может. Скорость 9600

Скрытый текст


/* Includes ------------------------------------------------------------------*/
#include "stm32f0xx_hal.h"
#include "dma.h"
#include "i2c.h"
#include "spi.h"
#include "usart.h"
#include "gpio.h"

/* USER CODE BEGIN Includes */
#include "lib_7219.h"
#include "string.h"
#include <stdio.h>
#include "stdlib.h"
/* USER CODE END Includes */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
#define MAXSTRING 20
#define UART_PACKET_OK 0
#define UART_PACKET_TOO_LONG 1
#define UART_PACKET_CORRUPT 2
#define UART_BUSY 1
#define UART_CPLT 0

volatile uint8_t UART_TX_Busy = 0;
uint8_t UART_NewMessage = 0;
uint8_t UART1_rxBuffer = '\000';
char rxString[MAXSTRING];

uint8_t TimerData[8] = {0,0,0,0,0,0,0,0};
uint8_t OldTimerData[8] = {0,0,0,0,0,0,0,0};
uint8_t TimerDataNew = 0;
uint8_t ScreenTime[24] = {0,1,0,1, 0,2,0,2, 0,3,0,3, 0,4,0,4, 0,5,0,5, 0,6,0,6};
char SendingTime[14];

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
void Error_Handler(void);

/* Private function prototypes -----------------------------------------------*/
void UART_Send (const char message[]);
void UART_CommandProcessor (void);
void Timer_read(void);
void TimerWrite(uint8_t, uint8_t);
void DisplayTime(void);
void SendTime(void);
void TimeCorrection(void);
void DayNight (void);

int main(void)
{

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* Configure the system clock */
  SystemClock_Config();

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_SPI1_Init();
  MX_I2C1_Init();
  MX_USART1_UART_Init();

	HAL_UART_Receive_DMA(&huart1, &UART1_rxBuffer, 1);
		
	StartDisplayTest(TEST_ON);
	HAL_Delay(1000);
	StartDisplayTest(TEST_OFF);
	HAL_Delay(1000);
	
	SetScanStart(NORMAL_OPERATION);
	SetScanLimit(0x05);
	SetDecodeMode(0xFF);
	
	// restore intensity level
	uint8_t intense_addr = 0x03;
	HAL_I2C_Master_Transmit(&hi2c1, 0xD0, &intense_addr, 1, 0xFFFF);
	HAL_I2C_Master_Receive(&hi2c1, 0xD0, &TimerData[3], 1, 0xFFFF);
	SetIntensity((TimerData[3]&0xF0)>>4);
	
	UART_Send("Timekeeper. V1. 09.2016. Uart started\n");

  while (1)
  {
		if(UART_NewMessage)	
		{
			UART_CommandProcessor();
			UART_NewMessage = 0;
		}
		Timer_read();
		DisplayTime();
		SendTime();
		TimeCorrection();
  }
}

void UART_Send (const char message[])
{
	while(UART_TX_Busy){};
	UART_TX_Busy = 1;
	HAL_UART_Transmit_DMA(&huart1, (uint8_t*)message, strlen(message));
}

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart1)
{
	UART_TX_Busy = 0;
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart1)
{
	static short int UART1_rxindex = 0;	
	static uint8_t UART1_ErrorFlag = UART_PACKET_OK;

	if (UART1_rxBuffer == 8 || UART1_rxBuffer == 127) // If Backspace or del
	{
		UART1_rxindex--; 
		if (UART1_rxindex < 0) UART1_rxindex = 0;
	}

	else if (UART1_rxBuffer == '\n') // If Enter
	{
		if (UART1_ErrorFlag == UART_PACKET_OK && UART1_rxindex)
		{
			rxString[UART1_rxindex] = 0;
			UART1_rxindex = 0;
			UART_NewMessage = 1;
		}
		else
		{
			UART_Send ("ERROR > UART1 packet too long\n");
			UART1_ErrorFlag = UART_PACKET_OK; // reset error state
		}
	}

	else
	{
		if (UART1_rxBuffer != '\r' && UART1_ErrorFlag == UART_PACKET_OK) // Ignore return
		{
			rxString[UART1_rxindex] = UART1_rxBuffer; // Add that character to the string
			UART1_rxindex++;
			if (UART1_rxindex >= MAXSTRING) // User typing too much, we can't have commands that big
			{
				UART1_ErrorFlag = UART_PACKET_TOO_LONG;
				UART1_rxindex = 0;
				rxString[UART1_rxindex] = '\000';
			}
		}
	}
}

// UART Commands decoder
// sett [HH.MM.SS] - set time
// setd [DD.MM.YY] - set date
// vctl - view control register
// sctl [OUT(1bit).FT(1bit).S(1bit).CAL(5bit)] - set control register
// sbrt [VAL] - set screen brightness
// any uknown string - HELP

void UART_CommandProcessor (void)
{
	char cmd_str_buf[4];
	static uint8_t command_recieved = 0;
		
	// copy command to buffer
	static char cmd_buf[MAXSTRING];
	strcpy(cmd_buf, rxString);
	
	// decode command
	if (strncmp("sett", cmd_buf, 4) == 0)  // if sett--------------------------------------
	{
		command_recieved = 1;
		
		uint8_t reg_buf = 0;
		
		reg_buf |= ((uint8_t)cmd_buf[6]-'0')|(((uint8_t)cmd_buf[5]-'0')<<4); // convert hours to BCD
		TimerWrite(0x02, reg_buf);
		reg_buf = 0;
		reg_buf |= ((uint8_t)cmd_buf[9]-'0')|(((uint8_t)cmd_buf[8]-'0')<<4); // convert minutes to BCD
		TimerWrite(0x01, reg_buf);
		reg_buf = 0;
		reg_buf |= ((uint8_t)cmd_buf[12]-'0')|(((uint8_t)cmd_buf[11]-'0')<<4); // convert seconds to BCD
		TimerWrite(0x00, reg_buf);
		
		UART_Send("Time is set\n");
	}
	
	if (strncmp("setd", cmd_buf, 4) == 0)  // if setd--------------------------------------
	{
		command_recieved = 1;
		
		uint8_t reg_buf = 0;
		reg_buf |= ((uint8_t)cmd_buf[6]-'0')|(((uint8_t)cmd_buf[5]-'0')<<4); // convert day to BCD
		TimerWrite(0x04, reg_buf);
		reg_buf = 0;
		reg_buf |= ((uint8_t)cmd_buf[9]-'0')|(((uint8_t)cmd_buf[8]-'0')<<4); // convert month to BCD
		TimerWrite(0x05, reg_buf);
		reg_buf = 0;
		reg_buf |= ((uint8_t)cmd_buf[12]-'0')|(((uint8_t)cmd_buf[11]-'0')<<4); // convert year to BCD
		TimerWrite(0x06, reg_buf);
		
		UART_Send("Date is set\n");
	}
	
	if (strncmp("vctl", cmd_buf, 4) == 0)  // if vctl--------------------------------------
	{
		command_recieved = 1;
		
		#define REGISTER_STRING 8
		static char EchoBuffer[REGISTER_STRING * 5 + 1];
	
		for (uint8_t i=0; i<REGISTER_STRING; i++)
		{
			sprintf(&EchoBuffer[i*5], "0x%02X", TimerData[i]);
			if (i>0) EchoBuffer[i*5-1] = ' ';
		}
		EchoBuffer[REGISTER_STRING * 5-1] = '\n';
		EchoBuffer[REGISTER_STRING * 5] = '\000';
		UART_Send("TimerData readed\n");
		UART_Send(EchoBuffer);
	}
	if (strncmp("sctl", cmd_buf, 4) == 0)  // if sctl--------------------------------------
	{
		command_recieved = 1;
		uint8_t reg_buf = atoi(&cmd_buf[5]);  	//convert param to int value
		TimerWrite(0x07, reg_buf);							//write value to ctrl reg
		UART_Send("Control register saved\n");	//echo message
	}
	
	if (strncmp("sbrt", cmd_buf, 4) == 0)  // if sbrt--------------------------------------
	{
		command_recieved = 1;
		
		strncpy(cmd_str_buf, &cmd_buf[5], 2);	// convert parameter to int
		uint8_t brightness = atoi(cmd_str_buf);
		
		if (brightness <= 0x0F) 								// check value
		{
			SetIntensity(brightness);

			uint8_t tmp;												// save brigtness in timer memory
			tmp = TimerData[3]&0x0F;
			tmp |= brightness<<4;
			TimerWrite(0x03,tmp);
			
			UART_Send("Intencity is set. Brightness saved in EEPROM\n");
		}
		else UART_Send("Incorrect param [00..15]\n");
	}
	
	if (!command_recieved)
	{
		UART_Send("Hello. This is timekeeper help\nsett HH.MM.SS - set time\nsetd DD.MM.YY - set date\nvctl - view control register\nsctl [OUT(1bit).FT(1bit).S(1bit).CAL(5bit)] - set control register\nsbrt [VAL] - set screen brightness\n"); 
	}
	command_recieved = 0;
}

void Timer_read(void)
{
	static uint8_t addr = 0;
	HAL_I2C_Master_Transmit(&hi2c1, 0xD0, &addr, 1, 0xFFFF);
	HAL_I2C_Master_Receive(&hi2c1, 0xD0, TimerData, 8, 0xFFFF);
}

void TimerWrite(uint8_t addr, uint8_t data)
{
	uint8_t tbuf[2] = {addr, data};
	// check I2C bus status?
	HAL_I2C_Master_Transmit(&hi2c1, 0xD0, tbuf, 2, 0xFFFF);
}

void DisplayTime(void)
{
	// time string format ScreenTime
	// [0] - date 10
	// [1] - date 10 position (0)
	// [2] - hours 10
	// [3] - hours 10 position (0)
	
	// [4] - date
	// [5] - date position (1)
	// [6] - hours
	// [7] - hours position (1)
	
	// [8] - month 10
	// [9] - month 10 position (2)
	// [10] - minutes 10
	// [11] - minutes 10 position (2)
	
	// [12] - month
	// [13] - month position (3)
	// [14] - minutes
	// [15] - minutes position (3)
	
	// [16] - year 10
	// [17] - year 10 position (4)
	// [18] - seconds 10
	// [19] - seconds 10 position (4)
	
	// [20] - year
	// [21] - year position (5)
	// [22] - seconds
	// [23] - seconds position (5)
	static uint8_t OldTimerData;
	
	if (TimerData[0]!=OldTimerData)
	{
		ScreenTime[0]  =  (TimerData[4]&0x30)>>4;			// date 10
		ScreenTime[2]  = ((TimerData[2]&0x30)>>4);		// hours 10
		ScreenTime[4]  =   TimerData[4]&0x0F;					// date
		ScreenTime[6]  =   TimerData[2]&0x0F;					// hours
		ScreenTime[8]  =  (TimerData[5]&0x10)>>4;			// month 10
		ScreenTime[10] =  (TimerData[1]&0x70)>>4;		// minutes 10
		ScreenTime[12] =   TimerData[5]&0x0F;					// month
		ScreenTime[14] =   TimerData[1]&0x0F;					// minutes
		ScreenTime[16] =  (TimerData[6]&0xF0)>>4;		// year 10
		ScreenTime[18] =  (TimerData[0]&0x70)>>4;		// seconds 10
		ScreenTime[20] =   TimerData[6]&0x0F;					// year
		ScreenTime[22] =   TimerData[0]&0x0F;					// seconds
			
		
		SetScanStart(NORMAL_OPERATION);
		SetScanLimit(0x05);
		SetDecodeMode(0xFF);
		SetIntensity((TimerData[3]&0xF0)>>4);
		
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
		HAL_SPI_Transmit(&hspi1, &ScreenTime[0],  2, 0xFF); 
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
		HAL_Delay(1);
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
		HAL_SPI_Transmit(&hspi1, &ScreenTime[4],  2, 0xFF); 
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
		HAL_Delay(1);
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
		HAL_SPI_Transmit(&hspi1, &ScreenTime[8],  2, 0xFF);
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);	
		HAL_Delay(1);
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
		HAL_SPI_Transmit(&hspi1, &ScreenTime[12], 2, 0xFF);
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);	
		HAL_Delay(1);
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
		HAL_SPI_Transmit(&hspi1, &ScreenTime[16], 2, 0xFF); 
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
		HAL_Delay(1);
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
		HAL_SPI_Transmit(&hspi1, &ScreenTime[20], 2, 0xFF);
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);	
		HAL_Delay(1);
		OldTimerData = TimerData[0];
	}
	
}

void SendTime (void)
{
	static uint8_t OldSeconds;
	
	if (ScreenTime[22]!=OldSeconds)
	{
		SendingTime[0] = ScreenTime[2]+'0';
		SendingTime[1] = ScreenTime[6]+'0';
		
		SendingTime[2] = ScreenTime[10]+'0';
		SendingTime[3] = ScreenTime[14]+'0';
		
		SendingTime[4] = ScreenTime[18]+'0';
		SendingTime[5] = ScreenTime[22]+'0';
		
		SendingTime[6] = ScreenTime[0]+'0';
		SendingTime[7] = ScreenTime[4]+'0';
		
		SendingTime[8] = ScreenTime[8]+'0';
		SendingTime[9] = ScreenTime[12]+'0';
		
		SendingTime[10] = ScreenTime[16]+'0';
		SendingTime[11] = ScreenTime[20]+'0';
		
		SendingTime[12] = '\n';	
		SendingTime[12] = '\n'; // zero terminate string
		
		OldSeconds = ScreenTime[22];
		
		UART_Send(SendingTime);
	}
}

void TimeCorrection(void)
{
	
}

void DayNight(void)
{
	
}
/** System Clock Configuration
*/
void SystemClock_Config(void)
{

  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;
  RCC_PeriphCLKInitTypeDef PeriphClkInit;

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL2;
  RCC_OscInitStruct.PLL.PREDIV = RCC_PREDIV_DIV2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }

  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1|RCC_PERIPHCLK_I2C1;
  PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK1;
  PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_SYSCLK;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }

  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  /* SysTick_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

void Error_Handler(void)
{
  while(1) 
  {
  }
}

 

все что тебе надо в этом коде есть. Индийский говнокод конечно, это я давно писал, но смысл понятен

Edited by mail_robot

Нужно делать то, что нужно. А то, что не нужно, делать не нужно. (С) Винни Пух

Share this post


Link to post
Share on other sites

Обновленный ассортимент тактовых кнопок Omron!

Компэл предлагает обновленный ассортимент миниатюрных тактовых кнопок производства компании Omron, который включает в себя разнообразные решения как для стандартных условий, так и для применения в условиях повышенной влажности.

Подробнее

17.10.2020 в 23:09, mail_robot сказал:

Дальше просто производится парсинг посимвольный и инкрементное формирование строки программой

Вот, это я и пытаюсь сделать, но куда формировать эту строку? Пытался копировать ее в char буфер, в принципе работало, но если передавать строку размером больше указанной в ...Recieve_IT то он просто обрубает не влезший кусок, хотя я сразу после от отправки строки обратно запускаю прерывание.

Подсмотрел как я реализовывал это дело в ардуино, там все проще, намного. Используется string в который можно добавлять символы пока память не треснет, а вот в STM я так и не смог подключить ни стринг, ни вектор - жалуется на дебри библиотеки iostream. Как это можно решить? Или есть какие-то ограничения не позволяющие использовать их? 

 

17.10.2020 в 23:09, mail_robot сказал:

но ограничен определенной максимальной, длиннее которой быть не может

Я пытаюсь вытащить все доступные точки WiFi из esp, но их может быть очень много, а всего для одной сети он дает полную характеристику, что занимает кучу места в буфере.

Да и данные от esp текут постоянно.

 

18.10.2020 в 18:03, MasterElectric сказал:

Или гугли что такое в UART IDLE. 

Полезная штука для передачи единичных команд.  

 

17.10.2020 в 23:09, mail_robot сказал:

Но с ДМА приятнее и можно использовать скорости порядка 3,5 мегабит

Куда нужна такая скорость? Все вот говорят, что для быстрых операций, но каких толком не говорят 

 

UPD: а где про все такое можно почитать? Просто куда не посмотри все все сами пишут и рассказывают, откуда они информацию берут? Есть что нибудь (видео, книга и тд и тп) где про вот это все расписано по полочкам, что куда и как?

Edited by xrou

Share this post


Link to post
Share on other sites

Вебинар «Экосистема MEAN WELL. Решения для любых задач электропитания» (20.05.2021)

Приглашаем 20 мая на вебинар, посвященный линейке поставок компании MEAN WELL и ее подходу к производству источников питания — как экосистемы продукции и услуг, которая позволяет подобрать оптимальный источник питания для любых задач электропитания. Рассмотрим весь спектр выпускаемой продукции MEAN WELL в области AC/DC-, DC/DC- и DC/AC-преобразователей с подробным разбором интересных и уникальных новинок, их применении и многое другое

Подробнее

1 час назад, xrou сказал:

Полезная штука для передачи единичных команд

Это флаг, по которому можно понять что передача пакета окончена. В хале даже функция такая есть если мне не изменяет склероз. 

Share this post


Link to post
Share on other sites

Трансиверы ADIN1200 и ADIN1300 от Analog Devices для промышленного Ethernet

ADIN1200 и ADIN1300 – микросхемы физического уровня Ethernet (PHY), разработанные ADI для современных промышленных систем Ethernet реального времени. Микросхемы ориентированы на применения в промышленной автоматике, автоматизации зданий, заводов, робототехнике и управлением движением, а также в промышленном интернете вещей (IIoT).

Подробнее

11 часов назад, xrou сказал:

Просто куда не посмотри все все сами пишут

так и есть. Никто не принесет и не подаст. Ставишь задачу, читаешь референц и еррату и пришешь


Нужно делать то, что нужно. А то, что не нужно, делать не нужно. (С) Винни Пух

Share this post


Link to post
Share on other sites

Я правильно из обсуждения понял, что ардуинского string у stm32 не существует точно так же, как и delay?


В действительности всё выглядит иначе, чем на самом деле. ©

Share this post


Link to post
Share on other sites

а это чо? Ктонить вообще читал мой код?

#include "string.h"

вектор ты не сделаешь, динамика в библиотеках STM отсутствует. Ну и как бы похоже дело не в бобине


Нужно делать то, что нужно. А то, что не нужно, делать не нужно. (С) Винни Пух

Share this post


Link to post
Share on other sites
14 минут назад, mail_robot сказал:

а это чо? Ктонить вообще читал мой код?

Если вопрос ко мне, то конечно нет. :D

Потому как мне сейчас не нужен этот код, вполне достаточно только понимания.

"string.h" - это Ваше личное творение?

 

Edited by smart_ed

В действительности всё выглядит иначе, чем на самом деле. ©

Share this post


Link to post
Share on other sites
7 часов назад, mail_robot сказал:

так и есть. Никто не принесет и не подаст

Не, я имею ввиду статьи про то как они все сами сделали исходя только из знания как работает uart.

 

5 часов назад, smart_ed сказал:

Я правильно из обсуждения понял, что ардуинского string у stm32 не существует точно так же, как и delay?

Ну стринг это вроде библиотечный класс и его можно подключить инклудом, а delay заменяется HAL_Delay

 

4 часа назад, mail_robot сказал:

вектор ты не сделаешь, динамика в библиотеках STM отсутствует.

Это особенность платформы? Жаль конечно, жизнь они облегчают сильно.

Share this post


Link to post
Share on other sites

Ну, что я короче сделал. Увеличил буфер. Память почти резиновая, так что можно.

Share this post


Link to post
Share on other sites
20.10.2020 в 20:10, xrou сказал:

Это особенность платформы?

компилятора и его библиотек. Нив Keil ни в кокосе добиться динамического выделения памяти я так и не смог. Думаю это ограничение связано с оглядкой на надежность. Везде где есть динамика это большая потенциальная дыра в надежности системы. Все ресурсы контроллера должны быть спланированы и зарезервированы жестко еще на этапе проектирования системы

string входит в состав библиотек компилятора (ну опять же как минимум в кайле и кокосе). Я не знаю почему у вас там не работает. Единственное надо конечно перед применением любой его функции ознакомиться с ее реализацией. Потому как там местами весьма и весьма отличается от типовых. Ну и памяти она конечно отжирает сразу прилично...

Edited by mail_robot

Нужно делать то, что нужно. А то, что не нужно, делать не нужно. (С) Винни Пух

Share this post


Link to post
Share on other sites

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Сообщения

    • Здесь он поставил резисторы, рвущие петлю. Но до конца они проблему не убирают. Пробуй по авторскому. Если не получится, резики выпаяешь и кинешь проводки от СЗ.
    • Походу, это  - самый весомый аргумент. Ну тут вопрос спорный, питающий провод  должен обеспечить требуемую нагрузку, и быть надёжным ("лапша" от паяльника не годится в питающий провод для ручного электроинструмента). Эти два основных требования делают разницу в проводах практически незаметной. С уважением, Сергей
    • @finn32 Как в Ланзаре с тобой делали? Играет сейчас до сих пор стоит, все нормально. Там на ОТ (текстолита кусочек) собраны все земли, так фон поборол. А тут по авторскому варианту будут те же грабли, если по его картинке собирать?
    • Доброго времени суток, уважаемые! Подскажите пожалуйста, можно ли как то выташить с кан шины некоторые параметры, и вывести их на отдельный дополнительный экран?  Сейчас для просмотра используется влютуз адаптер елм 327 v1. 5. Работает отлично, но! Что б смотреть нужно либо телефон постоянно держать включенным, либо конектить к магнитоле. Что затрудняем прослушивание музыки и использования других функций магнитолы, потому что отображает данные с елмки Если кто то делал подобные вещи, проконсультируйте пожалуйста.  С программированием я не дружу, так что, если есть хороший спец в данном вопросе, который сможет реализовать ПО, подскажите как с ним связаться:)  Спасибо. 
    • С Днём Радио!
  • Similar Content

    • By Михаил Дементьев
      Всем добрый день!
      Столкнулся с такой проблемой. Собрал самодельный igbt, и все хорошо работает, пока подаю на затвор напряжение с источника. Далее через ЦАП подключил stm32f100 к затвору и попытался управлять выходным током биполярника. В итоге вот что получилось: тестирую stm32 без igbt, ЦАП стабильно выдаёт то, чем я прошил микроконтроллер, но как только stm32 подключаю к затвору igbt, то stm32 перестаёт работать, в чем может быть проблема?
    • Guest Тот самый чайник
      By Guest Тот самый чайник
      Добрых времени суток, недавно начал изучать микроконтроллер STM32. Уже собрал контроллер в виде схемы, но не могу понять пару моментов а именно с подключением к нему датчиков. (буду благодарен если картинками кинете ещё).

      Микроконтроллер я как понял он питается и управляется с помощью 3.3В а 5В нежелательно,  поскольку мк может сгореть. Хотя многие говорят можно подать, а в дотушите нету упоминания, можете разъяснить этот момент. (знаю можно устранить с помощью подтягивающего резистора, но всё же, хочу знать от мнение асов и кто уже просветлён).

      Есть датчики температуры, уровень жидкости и её температура, скорости вращения. Их я как понимаю можно подключить на МК через усилитель, ФНЧ и комутатор аналоговых сигналов а затем на МК пустить. (питание через гальваническую развязку сделаю), так можно делать? Интересует схема этих датчиков которые я перечислил, желательно для промышленности поскольку не могу выбрать а какие-то не могу найти потому что не знаю что поставить. 

      Ещё читал что аналоговые датчики можно подключать напрямую из датчиков к МК (через делитель). Что скажите?

      И такой момент, на МК есть вводы и выводы. Т.е. программно в них можно прописать какой пин будет вводом а какой выводом? Дискретным или аналоговым, можете рассказать? Или на статью с разъяснением скиньте.

      Пока что так.

       
    • By admin
      В видео поговорим об энергоэффективности микроконтроллеров. Сравним потребление в режима сна arduino, blue pill с STM32F103 и представителя новой линейки энергоэффективных микроконтроллеров от st — STM32L552.
      Подробную информацию об линейке L5 можно найти тут: https://www.compel.ru/lib/143383
      Пи тест часть 1: https://youtu.be/ozu1IUjH1_Q
      Пи тест часть 2: https://youtu.be/uLOWYE-JJpA
    • By Стальной
      Доброго времени суток!
      Неделю не могу запустить DCMI на STM32F407VET6. 
      Работаю через HAL, инициализация кубом. К МК подключена камера OV7670. Камера дает картинку 640х480, и такое изображение мне негде хранить. Поэтому через фичу CROP хочу вырезать картинку 160х128 из центра под имеющийся экран.
      Ниже примерный код, без настройки камеры. Камера тактируется от 16 МГц MCO. Сигналы поступают на выводы МК, посмотрел осциллографом. У камеры есть некоторые настройки, которые тут в коде не показал, так как они влияют только на представление данных, но не на алгоритм захвата данных.
      /* USER CODE BEGIN PV */ uint16_t DCMI_data[20480] = {0}; //128*160=20480 words uint32_t ptr; /* USER CODE END PV */ //тут еще код куба, пропущу его int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_DMA_Init(); MX_DCMI_Init(); /* USER CODE BEGIN 2 */ HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET); //снять ресет с матрицы ptr = (uint32_t)(&DCMI_data[0]); HAL_Delay( 500 ); //начать резать с 512 клока строки (256 пиксель), начать резать с 160 строки //захватить 256 клоков (128 пикселей), захватить 160 строк HAL_DCMI_ConfigCrop(&hdcmi, 512, 160, 256, 160); HAL_DCMI_EnableCrop(&hdcmi); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ HAL_DCMI_Start_DMA(&hdcmi, DCMI_MODE_SNAPSHOT, ptr, 10240); //однократный захват, 10240 тетрад, 20480 слов, 160*128=40960 пикселей HAL_Delay(1500); } /* USER CODE END 3 */ } В результате в буфере ничего не появляется, DMA туда ничего не кладёт, проверил. Если не вызывать функцию EnableCrop, но какие-то данные появляются, но на экран их корректно отобразить не получается. Также пытался в камере обрезку включить, а не в МК - снова нет данных. Пробовал разные частоты тактирования матрицы давать - без разницы. Отладчиком увидел, что бит EN в регистре конфигурации потока  DMA не снимается, как будто DMA не получал запросов на транзакции. Помогите, пожалуйста, разобраться.
      Проект на яндексДиске
    • By Карен Григорян
      Здравствуйте, товарищи форумчане!
      У меня вот такая проблемка: есть такая схема:

      По сути тут stm32 на который подаётся некоторое постоянное напряжение, а именно на вход PA1. МК получает его, приводит в цифровую форму (разрядность АЦП равна восьми) и выводит их при помощи восьми GPIO выводов, а именно PB0-PB7. Эти выводы соединены со схемой ЦАП, которая преобразует значение, полученное от stm32 обратно в аналоговую форму и выводит в пробнике R2(1).
      Проблема в том результат выводится не верный. Точнее говоря не всегда верный. Когда я подаю 1В, то на выходе получаю 0,99В, что верно. Но когда, например, подаю 300мВ, то получаю 1.8В, что совсем не верно. Код прошивки предельно прост:
        while (1)
        {
              HAL_ADC_Start_IT(&hadc1);
              HAL_Delay(10);
      }
      Код колбека прерывания:
      void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
      {
          if(hadc->Instance == ADC1) //check if the interrupt comes from ACD1
          {
            int adc = HAL_ADC_GetValue(&hadc1);
                  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,(adc>>0)&1);
                  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,(adc>>1)&1);
                  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,(adc>>2)&1);
                  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,(adc>>3)&1);
                  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,(adc>>4)&1);
                  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,(adc>>5)&1);
                  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,(adc>>6)&1);
                  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,(adc>>7)&1);
          }
              }
      На всякий случай вот настройка АЦП в stm32:

      Вот пример неправильного вычисления:

×
×
  • Create New...