THI 0 4 марта, 2013 Опубликовано 4 марта, 2013 (изменено) · Жалоба Здравствуйте, уважаемые форумчане! Существует плата с неким функционалом для работы с пк через usb. Используемый мк был msp430, а теперь решили перейти на stm. И при первоначальных тестах у меня возникли 2 проблемы. Первая проблема - это отправка данных с платы через уарт на пк. На прием все работало хорошо. Открыл список регистров, выяснилось что в регистр USART1->DR не записываются данные. Решил проверить, запишется ли значение в usart2->dr. Добавил код настройки 2го уарта, запустил... и обнаружил, что в оба уарта теперь вообще ничего не записывается, ни в один регистр. Попытался убрать код, проблема осталась. Собственно, это 2 проблема. Используемый код #include "stm32f10x_gpio.h" #include "stm32f10x_rcc.h" int i; char* trans_dist; int trans_n, trans_cur; char flag_1 = 0; char text_1[]={'h','e','l','l','o'}; void Transmit_data(char* source, int n) { int i=0; for(;i<n;i++) { //volatile char temp; USART1->SR &= ~USART_SR_TC; while(!(USART1->SR & USART_SR_TXE)); USART1->DR = *source; //temp = USART1->DR; ++source; if (i==(n-1)) flag_1 = 0; } } int main(void) { RCC->CR|=RCC_CR_HSION; while (!(RCC->CR & RCC_CR_HSIRDY)); RCC->CFGR &=~RCC_CFGR_SW; RCC->CFGR |= RCC_CFGR_SW_HSI; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6,ENABLE); GPIOA->CRL |= GPIO_CRL_CNF1_0 | GPIO_CRL_CNF2_1 | GPIO_CRL_MODE2_1 | GPIO_CRL_CNF4_1 | GPIO_CRL_MODE4_1 | GPIO_CRL_CNF5_0 | GPIO_CRL_CNF6_0 | GPIO_CRL_CNF7_0; GPIOA->CRL &= ~(GPIO_CRL_CNF2_0 | GPIO_CRL_CNF4_0); GPIOA->CRH |= GPIO_CRH_CNF9_1 | GPIO_CRH_MODE9_1 | GPIO_CRH_CNF10_0 | GPIO_CRH_CNF12_1 | GPIO_CRH_MODE12_1; GPIOA->CRH &= ~(GPIO_CRH_CNF9_0 | GPIO_CRH_CNF12_0); GPIOB->CRL |= GPIO_CRL_MODE0_1 | GPIO_CRL_MODE1_1 | GPIO_CRL_MODE2_1; GPIOB->CRH |= GPIO_CRH_MODE10_1 | GPIO_CRH_MODE12_1 | GPIO_CRH_CNF13_0; GPIOC->CRH |= GPIO_CRH_CNF13_0; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO , ENABLE); USART1->BRR = (8000000+19200/2)/19200; USART1->CR1 |= USART_CR1_RXNEIE | USART_CR1_TE | USART_CR1_RE; USART1->CR1 |= USART_CR1_UE; //USART2->BRR = (8000000+19200/2)/19200; //USART2->CR1 |= USART_CR1_RXNEIE | USART_CR1_TE | USART_CR1_RE; //USART2->CR1 |= USART_CR1_UE; NVIC_EnableIRQ(USART1_IRQn); while(1) { if (flag_1) Transmit_data(text_1, 5); //USART1->DR |= 49; } } void USART1_IRQHandler(void) { //char t; if(USART1->SR & USART_SR_RXNE) { flag_1 = 1; USART1->SR &= ~USART_SR_RXNE; //t = USART1->DR; } if(USART1->SR & USART_SR_TXE) { //USART1->SR &= ~USART_SR_TXE; } } PA2 и PA3 - выход и вход для usart2, PA9 и PA10 - выход и вход для usart1 Среда: CooCox CoIDE 1.6.2, мк: stm32f100c4 Интересно ваше мнение по поводу обеих проблем. Изменено 6 марта, 2013 пользователем IgorKossak [codebox] для длинного кода, [code] - для короткого!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kan35 7 4 марта, 2013 Опубликовано 4 марта, 2013 · Жалоба У вас вроде бы GPIO настроены не верно. Все альтернативные порты USART должны быть настроены как alternative push pull (и RX и TX линии). И в функции передатчика вы делаете сброс битов не рекомендованным способом, из чего вывод - лучше используйте библиотеки ST, особенно в настройке GPIO это актуально - код нечитаем, оттого и ошибки. Тем более, библиотеки у вас подключены уже как видно из команд подачи тактирования на USART. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
maksimp 0 4 марта, 2013 Опубликовано 4 марта, 2013 (изменено) · Жалоба в регистр USART1->DR не записываются данные. Почему вы решили что не записываются? Записали, потом считали и сравнили с тем что записывали? Но USARTx->DR - это на самом деле 2 независимых регистра. При записи это регистр данных передатчика, при чтении - регистр данных приёмника. В общем случае прочтённое из этого регистра не равно тому что только что в него было записано. Отмечу что отладчик не имеет магического способа доступа к регистрам, он их пишет и читает так же как и программа процессорного ядра. Просмотр USARTx->DR в отладчике приводит к потере принятых данных, так как при этом флаг наличия данных сбрасывается. Все альтернативные порты USART должны быть настроены как alternative push pull (и RX и TX линии). Нет, RX должна быть настроена как вход или вход с подтяжкой. TX - да, alternative push pull (но при необходимости можно и alternative open drain). Изменено 4 марта, 2013 пользователем maksimp Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
THI 0 6 марта, 2013 Опубликовано 6 марта, 2013 · Жалоба kan35, maksimp спасибо что откликнулись И в функции передатчика вы делаете сброс битов не рекомендованным способом, из чего вывод - лучше используйте библиотеки ST, особенно в настройке GPIO это актуально - код нечитаем, оттого и ошибки. Тем более, библиотеки у вас подключены уже как видно из команд подачи тактирования на USART. Настройка GPIO сделана вручную из-за того, что есть некоторые выводы должны быть настроены как "push-pull", другие как "input floating". Недавно сел за CooCox, необходимой функции настройки не нашел, а GPIO_Init не подходит. По поводу сброса битов - это да, спасибо. Но USARTx->DR - это на самом деле 2 независимых регистра. При записи это регистр данных передатчика, при чтении - регистр данных приёмника. В общем случае прочтённое из этого регистра не равно тому что только что в него было записано. Отмечу что отладчик не имеет магического способа доступа к регистрам, он их пишет и читает так же как и программа процессорного ядра. Просмотр USARTx->DR в отладчике приводит к потере принятых данных, так как при этом флаг наличия данных сбрасывается. По поводу регистра DR - каюсь, видимо плохо читал документацию, буду перечитывать, может и ещё что найду. А вот по поводу отладчика сам бы нескоро догадался, спасибо. И все-таки, чем могла быть вызвана вторая проблема и можно ли ее как то исправить? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Elcarnado 0 7 марта, 2013 Опубликовано 7 марта, 2013 (изменено) · Жалоба Здравствуйте! Я тоже недавно начал разбираться с STM32, так что подсказать мало чем смогу, но мою настройку рабочего USART с радостью предоставлю, может поможет... #define USART_DBG_GPIO GPIOA #define USART_DBG_GPIO_CLK RCC_APB2Periph_GPIOA #define USART_DBG_RxPin GPIO_Pin_10 #define USART_DBG_TxPin GPIO_Pin_9 void USART_Configure(unsigned int baudrate) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; /* Enable GPIO and USART_DBG clock */ RCC_APB2PeriphClockCmd(USART_DBG_GPIO_CLK | USART_DBG_CLK | RCC_APB2Periph_AFIO, ENABLE); /* Configure USART_DBG Tx */ GPIO_InitStructure.GPIO_Pin = USART_DBG_TxPin; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // Скорость обновления пина GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // Режим - альтернативный Push-Pull GPIO_Init(USART_DBG_GPIO, &GPIO_InitStructure); /* Configure USART_DBG Rx */ GPIO_InitStructure.GPIO_Pin = USART_DBG_RxPin; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // Режим - Открытый вход GPIO_Init(USART_DBG_GPIO, &GPIO_InitStructure); /* Caonfigure USART parameters*/ USART_InitStructure.USART_BaudRate = baudrate; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART_DBG, &USART_InitStructure); USART_Cmd(USART_DBG, ENABLE); USART_SendData(USART_DBG,'A'); // Отправляем символ А в порт } Еще один # define забыл )) Необходимо добавить #define USART_DBG_CLK RCC_APB2Periph_USART1 Изменено 7 марта, 2013 пользователем IgorKossak [codebox] для длинного кода, [code] - для короткого!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
THI 0 7 марта, 2013 Опубликовано 7 марта, 2013 · Жалоба Elcarnado спасибо за пример, но я уже пробовал настраивать уарт через USART_Init, не помогло. Ещё вопрос, по конкретнее, существует ли биты блокировки настройки USART'а? Я правда таких не нашел, но думаю стоит спросить. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 7 марта, 2013 Опубликовано 7 марта, 2013 · Жалоба существует ли биты блокировки настройки USART'а?Это биты, отключающие его тактирование. Без тактирования ни один из регистров писаться не будет, читаться будут нули. Других нету. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
maksimp 0 7 марта, 2013 Опубликовано 7 марта, 2013 (изменено) · Жалоба существует ли биты блокировки настройки USART'а? Ещё есть регистры сброса периферии RCC_APB1RSTR и RCC_APB2RSTR (п. 7.3.4, 7.3.5 в reference manual). Если выставить в них бит в то работа соответствующего модуля блокируется. Добавил код настройки 2го уарта, запустил... и обнаружил, что в оба уарта теперь вообще ничего не записывается, ни в один регистр. Вы разрешили прерывания от USART2, но обработчик прерывания не написали. Прерывание происходит, флаг прерывания не сбрасывается, прерывание снова тут же проиходит и т.д. Программа перестаёт выполняться. Изменено 7 марта, 2013 пользователем maksimp Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
THI 0 23 марта, 2013 Опубликовано 23 марта, 2013 (изменено) · Жалоба Всем спасибо, кто ответил, извиняюсь, что так долго не писал. Вобщем 2 проблема решилась загрузкой другой прошивки, написанной, собственно, по примеру Elcarnado. Потом была залита предыдущая прошивка, настройка уарта работает. В чем была причина так и не разобрались. Второй уарт также был проверен (косвенно), похоже что ситуация такая же, как и с первым. maksimp Как я писал, настройка 2 уарта делается, по крайней мере, причина была не в прерываниях. Изменено 23 марта, 2013 пользователем THI Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Rimsky 0 8 марта, 2014 Опубликовано 8 марта, 2014 (изменено) · Жалоба Здравствуйте друзья. Инициализировал USART1 (МК STM32F100C4T6) при помощи стандартной библиотеки STDLib GPIO_InitTypeDef GPIO_InitStruct; USART_InitTypeDef USART_InitStructure; #if !defined REMAP_USART1 // Включаем тактирование порта А и USART1 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE); // Настраиваем ногу TxD (PA9) как выход push-pull c альтернативной функцией GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStruct); #else /** USART1 GPIO Configuration PB6 ------> USART1_TX PB7 ------> USART1_RX */ /*Enable or disable APB2 peripheral clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO | RCC_APB2Periph_USART1, ENABLE); /*Configure GPIO pin */ GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOB, &GPIO_InitStruct); /*Configure GPIO pin */ GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOB, &GPIO_InitStruct); /*Configure peripheral I/O remapping */ GPIO_PinRemapConfig(GPIO_Remap_USART1, ENABLE); #endif USART_StructInit(&USART_InitStructure); USART_InitStructure.USART_BaudRate = 9600*2; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_Init(USART1, &USART_InitStructure); /* Enable the USART1 */ USART_Cmd(USART1, ENABLE); /* Enable USART1 Receive and send interrupts */ USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); USART_ITConfig(USART1, USART_IT_TC, ENABLE); NVIC_EnableIRQ(USART1_IRQn); // Разрешение прерывания USART1 Но вот символьная скорость вместо 9600 бод как заказывал, в 2 раза меньше. В чем может быть причина? Изменено 8 марта, 2014 пользователем IgorKossak [codebox] для длинного кода, [code] - для короткого!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Rimsky 0 8 марта, 2014 Опубликовано 8 марта, 2014 (изменено) · Жалоба Открыл исходник (stm32f10x_usart.c) там в функции USART_Init(...) обнаружен такие строчки : /* USART OverSampling-8 Mask */ #define CR1_OVER8_Set ((u16)0x8000) /* USART OVER8 mode Enable Mask */ #define CR1_OVER8_Reset ((u16)0x7FFF) /* USART OVER8 mode Disable Mask */ if ((USARTx->CR1 & CR1_OVER8_Set) != 0) { /* Integer part computing in case Oversampling mode is 8 Samples */ integerdivider = ((25 * apbclock) / (2 * (USART_InitStruct->USART_BaudRate))); } else /* if ((USARTx->CR1 & CR1_OVER8_Set) == 0) */ { /* Integer part computing in case Oversampling mode is 16 Samples */ integerdivider = ((25 * apbclock) / (4 * (USART_InitStruct->USART_BaudRate))); } Кто объяснит, где в регистре USART_CR1 бит (CR1_OVER8) ??? Разобрался, для корректной работы с SPL нужно определить HSE_VALUE (частоту внешнего кварца), если это значение не определено, то из файла STM32f10x.h подставляется дефолтное: #if !defined HSE_VALUE #ifdef STM32F10X_CL #define HSE_VALUE ((uint32_t)25000000) /*!< Value of the External oscillator in Hz */ #else #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ #endif /* STM32F10X_CL */ #endif /* HSE_VALUE */ Изменено 8 марта, 2014 пользователем Rimsky Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 8 марта, 2014 Опубликовано 8 марта, 2014 · Жалоба Кто объяснит, где в регистре USART_CR1 бит (CR1_OVER8) ??? Reference manual только и объяснит. Читали? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Rimsky 0 8 марта, 2014 Опубликовано 8 марта, 2014 · Жалоба Reference manual только и объяснит. Читали? Читал, только в МК STM32F100C4T6 такого бита в регистре USART_CR1 нет. В прочем с этим я разобрался. :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 9 марта, 2014 Опубликовано 9 марта, 2014 · Жалоба В прочем с этим я разобрался. :) И какое же правильный ответ? Определить HSE_VALUE? 1. По поводу OVER8. В других МК он есть на месте 15 бита. В F100 он жестко обнулен, что соответствует 16 выборкам. Позицию бита можно было узнать из RM на дригие МК или по маске из библиотеки. В RM на ваш МК можно найти фразу, что начиная с 14 бита по 31 в регистре CR1 железные нули. 2. По поводу HSE_VALUE. Я не фанат стандартной библиотеки, но когда только она появилась и долгое время после имел некоторые проблемы как раз с HSE_VALUE. Дело в том, что для внешнего кварца у STM приняты стандартные значения в 8 или 25 МГц, а я (уж так сложилось исторически) применяю кварцы на 12 МГц. Делители библиотека рассчитывает исходя из заданного HSE_VALUE и стандартного для указанного семейства кварца. Я правил код библиотеки под себы, но это великое зло. Интересно, это до сих пор так? (вопрос разобравшемуся человеку :)) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Rimsky 0 9 марта, 2014 Опубликовано 9 марта, 2014 · Жалоба 1. По поводу OVER8. В других МК он есть на месте 15 бита. В F100 он жестко обнулен, что соответствует 16 выборкам. Позицию бита можно было узнать из RM на дригие МК или по маске из библиотеки. В RM на ваш МК можно найти фразу, что начиная с 14 бита по 31 в регистре CR1 железные нули. В общем так я и поступил. Смутило то, что SPL взято с stm32gui_lib в котором идет явная привязка к МК STM32F10x.... 2. По поводу HSE_VALUE. Я не фанат стандартной библиотеки, но когда только она появилась и долгое время после имел некоторые проблемы как раз с HSE_VALUE. Дело в том, что для внешнего кварца у STM приняты стандартные значения в 8 или 25 МГц, а я (уж так сложилось исторически) применяю кварцы на 12 МГц. Делители библиотека рассчитывает исходя из заданного HSE_VALUE и стандартного для указанного семейства кварца. Я правил код библиотеки под себы, но это великое зло. Интересно, это до сих пор так? (вопрос разобравшемуся человеку :)) В расчете baud rate для USARTA есть вызов процедуры RCC_GetClocksFreq(&RCC_ClocksStatus); Которая инициализирует значения структуры RCC_ClocksStatus элементы которой участвуют в расчете. В этой процедуре и фигурирует определение HSE_VALUE. Если оно не соответствует Вашему кварцу, то и расчет будет не верным. У меня кварц на 4096000, что отличается от дефолтного в 2 раза, вот тут то и были грабли. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться