|
Проблема с usart, не записывает значения в регистры |
|
|
|
Mar 4 2013, 13:57
|
Группа: Новичок
Сообщений: 4
Регистрация: 4-03-13
Пользователь №: 75 886

|
Здравствуйте, уважаемые форумчане! Существует плата с неким функционалом для работы с пк через usb. Используемый мк был msp430, а теперь решили перейти на stm. И при первоначальных тестах у меня возникли 2 проблемы. Первая проблема - это отправка данных с платы через уарт на пк. На прием все работало хорошо. Открыл список регистров, выяснилось что в регистр USART1->DR не записываются данные. Решил проверить, запишется ли значение в usart2->dr. Добавил код настройки 2го уарта, запустил... и обнаружил, что в оба уарта теперь вообще ничего не записывается, ни в один регистр. Попытался убрать код, проблема осталась. Собственно, это 2 проблема. Используемый код CODE #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 Интересно ваше мнение по поводу обеих проблем.
Сообщение отредактировал IgorKossak - Mar 6 2013, 07:26
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
|
|
|
|
|
Mar 4 2013, 17:28
|
Местный
  
Группа: Участник
Сообщений: 313
Регистрация: 2-07-11
Пользователь №: 66 023

|
Цитата(THI @ Mar 4 2013, 16:57)  в регистр USART1->DR не записываются данные. Почему вы решили что не записываются? Записали, потом считали и сравнили с тем что записывали? Но USARTx->DR - это на самом деле 2 независимых регистра. При записи это регистр данных передатчика, при чтении - регистр данных приёмника. В общем случае прочтённое из этого регистра не равно тому что только что в него было записано. Отмечу что отладчик не имеет магического способа доступа к регистрам, он их пишет и читает так же как и программа процессорного ядра. Просмотр USARTx->DR в отладчике приводит к потере принятых данных, так как при этом флаг наличия данных сбрасывается. Цитата(kan35 @ Mar 4 2013, 20:12)  Все альтернативные порты USART должны быть настроены как alternative push pull (и RX и TX линии). Нет, RX должна быть настроена как вход или вход с подтяжкой. TX - да, alternative push pull (но при необходимости можно и alternative open drain).
Сообщение отредактировал maksimp - Mar 4 2013, 18:32
|
|
|
|
|
Mar 6 2013, 19:20
|
Группа: Новичок
Сообщений: 4
Регистрация: 4-03-13
Пользователь №: 75 886

|
kan35, maksimp спасибо что откликнулись Цитата И в функции передатчика вы делаете сброс битов не рекомендованным способом, из чего вывод - лучше используйте библиотеки ST, особенно в настройке GPIO это актуально - код нечитаем, оттого и ошибки. Тем более, библиотеки у вас подключены уже как видно из команд подачи тактирования на USART. Настройка GPIO сделана вручную из-за того, что есть некоторые выводы должны быть настроены как "push-pull", другие как "input floating". Недавно сел за CooCox, необходимой функции настройки не нашел, а GPIO_Init не подходит. По поводу сброса битов - это да, спасибо. Цитата Но USARTx->DR - это на самом деле 2 независимых регистра. При записи это регистр данных передатчика, при чтении - регистр данных приёмника. В общем случае прочтённое из этого регистра не равно тому что только что в него было записано. Отмечу что отладчик не имеет магического способа доступа к регистрам, он их пишет и читает так же как и программа процессорного ядра. Просмотр USARTx->DR в отладчике приводит к потере принятых данных, так как при этом флаг наличия данных сбрасывается. По поводу регистра DR - каюсь, видимо плохо читал документацию, буду перечитывать, может и ещё что найду. А вот по поводу отладчика сам бы нескоро догадался, спасибо. И все-таки, чем могла быть вызвана вторая проблема и можно ли ее как то исправить?
|
|
|
|
|
Mar 7 2013, 07:16
|
Участник

Группа: Участник
Сообщений: 16
Регистрация: 27-02-13
Пользователь №: 75 819

|
Здравствуйте! Я тоже недавно начал разбираться с STM32, так что подсказать мало чем смогу, но мою настройку рабочего USART с радостью предоставлю, может поможет... CODE #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
Сообщение отредактировал IgorKossak - Mar 7 2013, 15:11
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
|
|
|
|
|
Mar 7 2013, 09:52
|
Группа: Новичок
Сообщений: 4
Регистрация: 4-03-13
Пользователь №: 75 886

|
Elcarnado спасибо за пример, но я уже пробовал настраивать уарт через USART_Init, не помогло. Ещё вопрос, по конкретнее, существует ли биты блокировки настройки USART'а? Я правда таких не нашел, но думаю стоит спросить.
|
|
|
|
|
Mar 7 2013, 20:00
|
Местный
  
Группа: Участник
Сообщений: 313
Регистрация: 2-07-11
Пользователь №: 66 023

|
Цитата(THI @ Mar 7 2013, 12:52)  существует ли биты блокировки настройки USART'а? Ещё есть регистры сброса периферии RCC_APB1RSTR и RCC_APB2RSTR (п. 7.3.4, 7.3.5 в reference manual). Если выставить в них бит в то работа соответствующего модуля блокируется. Цитата(THI @ Mar 4 2013, 16:57)  Добавил код настройки 2го уарта, запустил... и обнаружил, что в оба уарта теперь вообще ничего не записывается, ни в один регистр. Вы разрешили прерывания от USART2, но обработчик прерывания не написали. Прерывание происходит, флаг прерывания не сбрасывается, прерывание снова тут же проиходит и т.д. Программа перестаёт выполняться.
Сообщение отредактировал maksimp - Mar 7 2013, 20:08
|
|
|
|
|
Mar 23 2013, 12:36
|
Группа: Новичок
Сообщений: 4
Регистрация: 4-03-13
Пользователь №: 75 886

|
Всем спасибо, кто ответил, извиняюсь, что так долго не писал. Вобщем 2 проблема решилась загрузкой другой прошивки, написанной, собственно, по примеру Elcarnado. Потом была залита предыдущая прошивка, настройка уарта работает. В чем была причина так и не разобрались. Второй уарт также был проверен (косвенно), похоже что ситуация такая же, как и с первым. maksimp Как я писал, настройка 2 уарта делается, по крайней мере, причина была не в прерываниях.
Сообщение отредактировал THI - Mar 23 2013, 12:38
|
|
|
|
|
Mar 8 2014, 09:28
|

Группа: Участник
Сообщений: 14
Регистрация: 10-06-12
Пользователь №: 72 261

|
Здравствуйте друзья. Инициализировал USART1 (МК STM32F100C4T6) при помощи стандартной библиотеки STDLib CODE 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 раза меньше. В чем может быть причина?
Сообщение отредактировал IgorKossak - Mar 8 2014, 10:03
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
|
|
|
|
|
Mar 8 2014, 11:50
|

Группа: Участник
Сообщений: 14
Регистрация: 10-06-12
Пользователь №: 72 261

|
Открыл исходник (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 */
Сообщение отредактировал Rimsky - Mar 8 2014, 11:51
|
|
|
|
|
Mar 8 2014, 23:59
|

Группа: Участник
Сообщений: 14
Регистрация: 10-06-12
Пользователь №: 72 261

|
Цитата(adnega @ Mar 8 2014, 20:51)  Reference manual только и объяснит. Читали? Читал, только в МК STM32F100C4T6 такого бита в регистре USART_CR1 нет. В прочем с этим я разобрался.
|
|
|
|
|
Mar 9 2014, 05:36
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
Цитата(Rimsky @ Mar 9 2014, 03:59)  В прочем с этим я разобрался.  И какое же правильный ответ? Определить HSE_VALUE? 1. По поводу OVER8. В других МК он есть на месте 15 бита. В F100 он жестко обнулен, что соответствует 16 выборкам. Позицию бита можно было узнать из RM на дригие МК или по маске из библиотеки. В RM на ваш МК можно найти фразу, что начиная с 14 бита по 31 в регистре CR1 железные нули. 2. По поводу HSE_VALUE. Я не фанат стандартной библиотеки, но когда только она появилась и долгое время после имел некоторые проблемы как раз с HSE_VALUE. Дело в том, что для внешнего кварца у STM приняты стандартные значения в 8 или 25 МГц, а я (уж так сложилось исторически) применяю кварцы на 12 МГц. Делители библиотека рассчитывает исходя из заданного HSE_VALUE и стандартного для указанного семейства кварца. Я правил код библиотеки под себы, но это великое зло. Интересно, это до сих пор так? (вопрос разобравшемуся человеку  )
|
|
|
|
|
Mar 9 2014, 08:06
|

Группа: Участник
Сообщений: 14
Регистрация: 10-06-12
Пользователь №: 72 261

|
Цитата(adnega @ Mar 9 2014, 14:36)  1. По поводу OVER8. В других МК он есть на месте 15 бита. В F100 он жестко обнулен, что соответствует 16 выборкам. Позицию бита можно было узнать из RM на дригие МК или по маске из библиотеки. В RM на ваш МК можно найти фразу, что начиная с 14 бита по 31 в регистре CR1 железные нули. В общем так я и поступил. Смутило то, что SPL взято с stm32gui_lib в котором идет явная привязка к МК STM32F10x.... Цитата(adnega @ Mar 9 2014, 14:36)  2. По поводу HSE_VALUE. Я не фанат стандартной библиотеки, но когда только она появилась и долгое время после имел некоторые проблемы как раз с HSE_VALUE. Дело в том, что для внешнего кварца у STM приняты стандартные значения в 8 или 25 МГц, а я (уж так сложилось исторически) применяю кварцы на 12 МГц. Делители библиотека рассчитывает исходя из заданного HSE_VALUE и стандартного для указанного семейства кварца. Я правил код библиотеки под себы, но это великое зло. Интересно, это до сих пор так? (вопрос разобравшемуся человеку  ) В расчете baud rate для USARTA есть вызов процедуры RCC_GetClocksFreq(&RCC_ClocksStatus); Которая инициализирует значения структуры RCC_ClocksStatus элементы которой участвуют в расчете. В этой процедуре и фигурирует определение HSE_VALUE. Если оно не соответствует Вашему кварцу, то и расчет будет не верным. У меня кварц на 4096000, что отличается от дефолтного в 2 раза, вот тут то и были грабли.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|