реклама на сайте
подробности

 
 
> stm32 uart не отправляет строку, отправляются только одиночные символы
mempfis_
сообщение Feb 22 2012, 17:15
Сообщение #1


Профессионал
*****

Группа: Свой
Сообщений: 1 001
Регистрация: 27-06-06
Пользователь №: 18 409



Всем добрый вечер. Разбираюсь с stm32f10x. Столкнулся с проблемой uart.
Необходимо отправлять строки, а отправляются одиночные символы.

Обработчик перрывания

CODE
void USART2_IRQHandler(void)
{

// Recognizing the interrupt event
if(USART_GetFlagStatus(USART2,USART_FLAG_ORE))
{
USART_ClearFlag(USART2,USART_FLAG_ORE);
// Overrun Error
}
if(USART_GetFlagStatus(USART2,USART_FLAG_FE))
{
USART_ClearFlag(USART2,USART_FLAG_FE);
// Framing Error
}
if(USART_GetFlagStatus(USART2,USART_FLAG_NE))
{
USART_ClearFlag(USART2,USART_FLAG_NE);
// Noise Error
}
if(USART_GetFlagStatus(USART2,USART_FLAG_PE))
{
USART_ClearFlag(USART2,USART_FLAG_PE);
// Parity Error
}
// Push a new data into the receiver buffer
if(USART_GetFlagStatus(USART2,USART_FLAG_RXNE))
{
// Push a new data into the receiver buffer

Rx2Buf[Rx2Head++] = USART_ReceiveData(USART2);
if (Rx2Head >= US2_RXBUFSIZE) Rx2Head = 0;

}
if( USART_GetFlagStatus(USART2,USART_FLAG_TXE)
&& (USART_GetITStatus (USART2,USART_IT_TXE) == SET))
{

if (Tx2Tail != Tx2Head)
{
USART_SendData(USART2,Tx2Buf[Tx2Tail++]);
if (Tx2Tail >= US2_TXBUFSIZE) Tx2Tail = 0;
}
else
{
USART_ITConfig(USART2,USART_IT_TXE ,DISABLE);
}

}
}


инициализация uart
CODE
void UART2_init(unsigned int baudrate)
{
volatile Int8U Tmp;
USART_InitTypeDef UART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;


/* USART_InitStruct members default value */
UART_InitStructure.USART_BaudRate = baudrate;
UART_InitStructure.USART_WordLength = USART_WordLength_8b;
UART_InitStructure.USART_StopBits = USART_StopBits_1;
UART_InitStructure.USART_Parity = USART_Parity_No ;
UART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
UART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

// Init receive and transmit FIFOs
Rx2Head = 0;// the circular buffer index
Rx2Tail = 0;
Tx2Head = 0;// the circular buffer index
Tx2Tail = 0;


// Release reset and enable clock
USART_DeInit(USART2);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

// GPIO Init
// Enable GPIO clock and release reset
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, DISABLE);
GPIO_PinRemapConfig(GPIO_Remap_USART2,DISABLE);

// Assign PA2 to UART2 (Tx)
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_Init(GPIOA, &GPIO_InitStructure);

// Assign PA3 to UART2 (Rx)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_Init(GPIOA, &GPIO_InitStructure);

// Init UART2
USART_Init(USART2,&UART_InitStructure);

// Enable and configure the priority of the UART2 Update IRQ Channel
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = UART2_INTR_PRI;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

USART_ClearFlag(USART2, USART_FLAG_CTS | USART_FLAG_LBD |
USART_FLAG_TC | USART_FLAG_RXNE | USART_FLAG_IDLE |
USART_FLAG_ORE | USART_FLAG_NE | USART_FLAG_FE |
USART_FLAG_PE);

// Enable UART2 interrupts
USART_ITConfig(USART2,USART_IT_PE ,ENABLE);
USART_ITConfig(USART2,USART_IT_TC ,DISABLE);

//USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);
USART_ITConfig(USART2,USART_IT_RXNE,DISABLE);

USART_ITConfig(USART2,USART_IT_IDLE,DISABLE);
USART_ITConfig(USART2,USART_IT_LBD ,DISABLE);
USART_ITConfig(USART2,USART_IT_CTS ,DISABLE);
USART_ITConfig(USART2,USART_IT_ERR ,DISABLE);

// Enable the UART2
USART_Cmd(USART2, ENABLE);
}


процедура запихивания символа в fifo
CODE
void _putcharUART2(char data)
{
__disable_interrupt();


//USART_ITConfig(USART2,USART_IT_RXNE ,DISABLE); //запрещаем прерывание на приём

if( USART_GetITStatus (USART2,USART_IT_TXE) == RESET )
{
//прерывания по опустошению передающего регистра запрещены
//разрешаем прерывание

USART_SendData(USART2,data);
USART_ITConfig(USART2,USART_IT_TXE ,ENABLE);
}
else
{
//ложим байт в fifo
Tx2Buf[Tx2Head++] = data;
if (Tx2Head >= US2_TXBUFSIZE) Tx2Head = 0;
}

__enable_interrupt();
}


одиночные символы раз в 4 секунды отправляются.
А строка закинутая через
Код
void _putstringUART2( const char *pData) { while(*pData != 0x00) _putcharUART2( (char) (*pData++)); }

не отправляется.

Отправка по такому принципу 100% работает в lpc17 и sam7x.
Может чтото в коде упускаю?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов (1 - 2)
AHTOXA
сообщение Feb 22 2012, 18:47
Сообщение #2


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Попробуйте так:
Код
void _putcharUART2(char data)
{
    Tx2Buf[Tx2Head++] = data;          
    if (Tx2Head >= US2_TXBUFSIZE) Tx2Head = 0;
    USART_ITConfig(USART2,USART_IT_TXE  ,ENABLE);
}


И уберите проверку
&& (USART_GetITStatus (USART2,USART_IT_TXE) == SET))
в обработчике прерывания.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
mempfis_
сообщение Feb 23 2012, 10:01
Сообщение #3


Профессионал
*****

Группа: Свой
Сообщений: 1 001
Регистрация: 27-06-06
Пользователь №: 18 409



Спасибо. Вроде работает как надо.
Попутно задам вопрос по настройке тактового генератора и таймера.
На плате нет внешней rc-цепочки, использую внутреннюю.
Изменил инициализацию тактового генератора - закоментировал весь пункт 2.
В строке RCC_PLLConfig заменил RCC_PLLSource_HSE_Div1 на RCC_PLLSource_HSI_Div2

Теоретически я выбрал внутренний генератор на 8МГц/2 что соответствует частоте на выходе PLL 36МГц а не 72.

Но при этом uart2 у меня работает на требуемой скорости.
А таймер отстаёт.
Привожу инициализацию clk и таймера

Код
void ClkInit (void)
{
  // 1. Clocking the controller from internal HSI RC (8 MHz)
  RCC_HSICmd(ENABLE);
  // wait until the HSI is ready
  while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);
  RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);
  
  // // 2. Enable ext. high frequency OSC
  // RCC_HSEConfig(RCC_HSE_ON);
  // wait until the HSE is ready
  // while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);
  
  // 3. Init PLL
  RCC_PLLConfig(RCC_PLLSource_HSI_Div2,RCC_PLLMul_9); // 72MHz
  RCC_PLLCmd(ENABLE);
  // wait until the PLL is ready
  while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
  // 4. Set system clock dividers
  RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_1Div5);
  RCC_ADCCLKConfig(RCC_PCLK2_Div8);
  RCC_PCLK2Config(RCC_HCLK_Div1);
  RCC_PCLK1Config(RCC_HCLK_Div2);
  RCC_HCLKConfig(RCC_SYSCLK_Div1);
#ifdef EMB_FLASH
  // 5. Init Embedded Flash
  // Zero wait state, if 0 < HCLK 24 MHz
  // One wait state, if 24 MHz < HCLK 56 MHz
  // Two wait states, if 56 MHz < HCLK 72 MHz
  // Flash wait state
  FLASH_SetLatency(FLASH_Latency_2);
  // Half cycle access
  FLASH_HalfCycleAccessCmd(FLASH_HalfCycleAccess_Disable);
  // Prefetch buffer
  FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
#endif // EMB_FLASH
  // 5. Clock system from PLL
  RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
}

Код
Таймер в примере был настроен на прерывание раз в 200 мС.
Я его перестроил на прерывание раз в 1 мС.
//-------------------------------------------
void TimInit(void)
{
  
  TIM_TimeBaseInitTypeDef TIM1_TimeBaseInitStruct;
  NVIC_InitTypeDef NVIC_InitStructure;
  
  // Timer1 Init
  // Enable Timer1 clock and release reset
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
  RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM1,DISABLE);

  // Set timer period 0.2 sec
  TIM1_TimeBaseInitStruct.TIM_Prescaler = 720;  // 10us resolution
  TIM1_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
  TIM1_TimeBaseInitStruct.TIM_Period = 100; //1ms  //20000 200 ms
  TIM1_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
  TIM1_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
  TIM_TimeBaseInit(TIM1,&TIM1_TimeBaseInitStruct);

  // Clear update interrupt bit
  TIM_ClearITPendingBit(TIM1,TIM_FLAG_Update);
  // Enable update interrupt
  TIM_ITConfig(TIM1,TIM_FLAG_Update,ENABLE);

  NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQChannel;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 7;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

  // Enable timer counting
  TIM_Cmd(TIM1,ENABLE);
}
//-------------------------------------------


И напоследок - на схеме написано что процессор stm32f100cxt6. По документации мах. частота 24 МГц.
Но в настройках clk я не вижу подключения какого-либо делителя для системной частоты...

С таймером разобрался. Разрешение в 100 uS и период 1 мС.
Кстати индусы не особо заморачивались насчёт точности.
За счёт строки TIM1_TimeBaseInitStruct.TIM_Period = 10; вместо TIM1_TimeBaseInitStruct.TIM_Period = 9; тайер постоянно грешил на +100 uS.

Код
  TIM1_TimeBaseInitStruct.TIM_Prescaler = 3600;  // 100us resolution
  TIM1_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
  TIM1_TimeBaseInitStruct.TIM_Period = 9; //1ms
  TIM1_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
  TIM1_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
  TIM_TimeBaseInit(TIM1,&TIM1_TimeBaseInitStruct);

Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 28th July 2025 - 19:23
Рейтинг@Mail.ru


Страница сгенерированна за 0.01387 секунд с 7
ELECTRONIX ©2004-2016