STM32F103VET6 передача массива байт по USART
Добавлено: Вт сен 08, 2015 10:25:42
Решил переделать одну железку с AVR на STM32. На USART что то конкретно запутался. Мозг кипит уже. В общем среда CooCox, камень STM32F103VET6 работает на 72 МГц. Железка отсылает по RS485 массив AB CD 01 FF 88. Компьютер обратно присылает ответ DC BA 01 00 72 00 FD 00 FA. Задача: разобрать ответ и выполнить действия. Казалось бы банально, но я туплю и не понимаю
На AVR я задаю массив:
Включаю USART:
Разрешаю прерывание по приему байта и складываю принятые байты в буфер:
В основном цикле работаю с буфером и отправляю ответ:
Интервал между запросами считает таймер. Всё работает как часы!
Теперь хочу то же самое проделать на STM32.
Массив:
Для примера хочу помигать светодиодом в зависимости от принятой команды. Настраиваю пин для светодиода, пин для переключения приема/передачи и пины USART. Ещё запускаю таймер на отсчет 1 секунды.
Обработка прерываний:
Каждую секунду выставляем флаг USART_Enable_Send что пора передавать запрос.
1. Что нужно ещё добавить для стабильной работы USART? Может как то прерывания ещё настраивать надо?
2. Как правильно передать массив целиком? Как и самое главное где проверять окончание ПЕРЕДАЧИ? Перед отправкой следующего байта.
Надо что то ещё добавлять или нет? Потому что светодиод у меня на плате не загорается. При старте обмена он загорается и постоянно горит. Снифил обмен. Передача вроде как идет. Но через секунд 10 программа на ПК падает по ошибке порта (на AVR не падает). Какая ошибка не понятно. У меня подозрение что я что то не донастроил на STM32.
В общем хэлп, бьюсь об стену.
На AVR я задаю массив:
Код: Выделить всё
unsigned char Zapros[] = {0xAB,0xCD,0x01,0xFF,0x88}; Спойлер
Код: Выделить всё
// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud Rate: 38400
UCSRA=0x00;
UCSRB=0x98;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x17;
Спойлер
Код: Выделить всё
interrupt [USART_RXC] void usart_rx_isr(void)
{
char status,data;
status=UCSRA;
data=UDR;
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
{
buffer[counter] = data;
if (++counter == BUFFER_SIZE) {
counter = 0;
}
}
}
Спойлер
Код: Выделить всё
void SendCommand (unsigned char *command, unsigned char length) {
delay_ms(1); // ждем перед отправкой
DE = 1; // выставляем на передачу
while (length--) {
while(!(UCSRA & (1<<UDRE))); // ждем освобождения регистра UDR
UDR = *command++;
}
delay_ms(1); // ждем после отправки
DE = 0; // выставляем на прием
}
....
SendCommand(Zapros,5);
Теперь хочу то же самое проделать на STM32.
Массив:
Код: Выделить всё
uint8_t SendBuffer[] = {0xab,0xcd,0x01,0xff,0x88}; Спойлер
Код: Выделить всё
GPIO_InitTypeDef LED;
GPIO_InitTypeDef USART_PIN;
USART_InitTypeDef USART_InitStruct;
TIM_TimeBaseInitTypeDef TIM_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
// PE14 -> LED PIN
LED.GPIO_Pin = GPIO_Pin_14;
LED.GPIO_Mode = GPIO_Mode_Out_PP;
LED.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOE, &LED);
GPIO_SetBits(GPIOE,GPIO_Pin_14);
// PA9 -> TX USART
USART_PIN.GPIO_Pin = GPIO_Pin_9;
USART_PIN.GPIO_Mode = GPIO_Mode_AF_PP;
USART_PIN.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &USART_PIN);
//PA10 -> RX USART
USART_PIN.GPIO_Pin = GPIO_Pin_10;
USART_PIN.GPIO_Mode = GPIO_Mode_IN_FLOATING;
USART_PIN.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &USART_PIN);
// PA11 -> DE (RS485)
USART_PIN.GPIO_Pin = GPIO_Pin_11;
USART_PIN.GPIO_Mode = GPIO_Mode_Out_PP;
USART_PIN.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &USART_PIN);
USART_InitStruct.USART_BaudRate = 38400;
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
USART_InitStruct.USART_StopBits = USART_StopBits_1;
USART_InitStruct.USART_Parity = USART_Parity_No ;
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init (USART1, &USART_InitStruct);
USART_Cmd(USART1, ENABLE);
TIM_TimeBaseStructInit(&TIM_InitStructure);
TIM_InitStructure.TIM_Prescaler = 7200-1;
TIM_InitStructure.TIM_Period = 10000-1;
TIM_InitStructure.TIM_ClockDivision = 0;
TIM_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM6, &TIM_InitStructure);
TIM_Cmd(TIM6, ENABLE);
NVIC_EnableIRQ(TIM6_IRQn);
TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE);
NVIC_EnableIRQ(USART1_IRQn);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // разрешаем прерывания RX
Спойлер
Код: Выделить всё
void TIM6_IRQHandler(void)
{
if (TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM6, TIM_IT_Update);
USART_Enable_Send = 1;
}
}
void USART1_IRQHandler(void)
{
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
buffer[counter] = USART_ReceiveData(USART1);
if (++counter == BUFFER_SIZE) {
counter = 0;
}
}
}
Спойлер
Код: Выделить всё
while(1)
{
if (USART_Enable_Send == 1) {
SendCommand (SendBuffer,5);
USART_Enable_Send = 0;
}
if (counter > 8) {
for (i=0;i<8;i++) {
crc = crc + buffer[i]; // считаем контрольную сумму
}
i = (~crc + 1) & 0xFF; // берем 2 младших разряда от двоичного дополнения
if ( buffer[8] == i ) {
if ((buffer[7] & (1<<0)) == 1) { // если нулевой бит предпоследнего байта установлен (1)
GPIOE->BSRR = GPIO_BSRR_BS14; // зажечь светодиод
}
else {
GPIOE->BSRR = GPIO_BSRR_BR14;
}
USART1->DR = buffer[7];
}
counter = 0;
}
}
2. Как правильно передать массив целиком? Как и самое главное где проверять окончание ПЕРЕДАЧИ? Перед отправкой следующего байта.
Код: Выделить всё
void delay_ms(uint32_t ms) {
volatile uint32_t nCount;
RCC_ClocksTypeDef RCC_Clocks;
RCC_GetClocksFreq (&RCC_Clocks);
nCount = (RCC_Clocks.HCLK_Frequency/10000)*ms;
for (; nCount != 0; nCount--);
}
...
void SendCommand (uint8_t *command, uint8_t length) {
counter = 0;
GPIOA->BSRR = GPIO_BSRR_BS11; // выставляем DE на передачу
while (length--) {
while(!(USART1->SR & USART_SR_TC)); // ждем окончания передачи предыдущего байта
USART1->DR = *command++;
}
delay_ms(1); // ждем после отправки
GPIOA->BSRR = GPIO_BSRR_BR11; // выставляем DE на прием
}
В общем хэлп, бьюсь об стену.