Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: STM32L053 проблема с USART
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Ешь
Всем привет!
Использую плату STM32L053 Discovery с контроллером STM32L053C8T6, и не могу запустить USART. Чтобы не пробовал USART "молчит". Сейчас использую вот такой код, который взял от сюда и модифицировал под свой контроллер.

CODE
#include "stm32l0xx.h" // Device header

void Init(void); //Объявление функции инициализации RCC, GPIO, USART
void Usart1_Transmit(uint8_t); //Объявление функции передачи символа через USART
void Usart1_Transmit_str(char* str); //Объявление функции передачи строки через USART


int main()
{
Init(); //Вызов функции инициализации
while(1)
{
Usart1_Transmit_str("STM32L-DISCOVERY"); //Вызов функции передачи строки через USART
for(uint32_t i=0; i<0x002FFFFF; i++); //Временная задержка
}
}

void Init()
{
//RCC
RCC->CR |= RCC_CR_HSION; //Включаем тактовый генератор HSI
while(!(RCC_CR_HSIRDY)); //Ждем его стабилизации
RCC->CFGR |= RCC_CFGR_SW_HSI; //Выбираем источником тактовой частоты SYSCLK генератор HSI
RCC->CR &= ~RCC_CR_MSION; //Отключаем генератор MSI.

//GPIO
RCC->AHBENR |= RCC_IOPENR_GPIOAEN; //Включаем тактирование порта А
GPIOA->MODER |= GPIO_MODER_MODE9_1; //PA9 - выход AF
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_9; //PA9 - выход push-pull
GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPD9); //PA9 - без подтяжки
GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEED9; //PA9 - скорость 40 МГц
/*Далее в разряды AFRH9[3:0] регистра альтернативных функций GPIOA_AFRH записываем
значение 0100, тем самым для вывода PA9 задаем значение
альтернативной функции - AF4, что соответствует USART1_TX*/
GPIOA->AFR[1] |= (0x4<<4);


//USART1
RCC->APB2ENR |= RCC_APB2ENR_USART1EN; //Включаем тактирование модуля USART1
USART1->CR1 |= USART_CR1_UE; //Включаем USART1
USART1->CR1 &= ~USART_CR1_M; //Длина слова - 8 бит
USART1->CR2 &= ~USART_CR2_STOP; //1 стоп-бит
USART1->BRR = 0x683; //baud rate 9600 при частоте HSI = 16 МГц
USART1->CR1 |= USART_CR1_TE; //Разрешаем передачу данных
}

//Функци передачи символа через USART
void Usart1_Transmit(uint8_t data)
{
while(!(USART1->ISR & USART_ISR_TC)); //Ждем установки флага TC - завершения передачи
USART1->TDR = data;
}

//Функция передачи строки через USART
void Usart1_Transmit_str(char* str)
{
uint8_t i=0;
while(str[i])
{
Usart1_Transmit(str[i]);
i++;
}
Usart1_Transmit('n');
Usart1_Transmit('r');
}


На компьютер пробовал передавать используя и FT232 и ST-LINK (оба чипа работают как USART-USB - проверял). Сам контроллер работает, диодами мигает, предустановленная демо-прошивка тоже нормально работала. Не работает ни USART1, ни USART2, пробовал на разных ногах, все время одно и тоже.

В чем может быть проблема? С STM32 раньше не работал, но документацию прочитал уже вдоль и поперек и вроде все правильно.
Tarbal
Проблема может быть в разрешении модуля UART и в подключении тактов правильной частоты к его входу. Ну это не считая настройки, что вы по видимому сделали.
Хотя я тоже с ST только начал. У меня аналогичная проблема с SAI, но я ее решу. Обычно какя-нибудь простая вешь упущена и потом долго удивляешься своей невнимательности. Ускорить может если у кого-нибудь есть работающее устройство и он поделится содержимым регистров.
AHTOXA
Цитата(Ешь @ Nov 6 2015, 20:10) *
Код
//Функци передачи символа через USART
void Usart1_Transmit(uint8_t data)
{
  while(!(USART1->ISR & USART_ISR_TC)); //Ждем установки флага TC - завершения передачи
  USART1->TDR = data;
}

Ждать надо не TC, а TXE. В остальном, вроде, всё правильно.
Ешь
Цитата(Tarbal @ Nov 6 2015, 16:07) *
Проблема может быть в разрешении модуля UART и в подключении тактов правильной частоты к его входу.

Поясните вашу мысль пожалуйста. Мне кажется, если бы были проблемы с частотой, то я бы с UARTa получал бы какую-то абракадабру, а я не получаю вообще ничего.

Цитата(AHTOXA @ Nov 6 2015, 16:57) *
Ждать надо не TC, а TXE. В остальном, вроде, всё правильно.

Поправил, но ничего не поменялось. Так же сейчас задумался, похоже там не должно быть отрицания. В документации сказано, что 1 там ставится когда данные передались, т.е. эта строка так должна выглядить:

Код
while(USART1->ISR & USART_ISR_TXE); //Ждем установки флага TXE - конца передачи данных на сдвиговый регистр


После этой правки, он благополучно завис на этом месте. Видимо все-таки дело в том, что ещё нужно что-то инициализировать...
Tarbal
Цитата(Ешь @ Nov 6 2015, 21:09) *
Поясните вашу мысль пожалуйста. Мне кажется, если бы были проблемы с частотой, то я бы с UARTa получал бы какую-то абракадабру, а я не получаю вообще ничего.


Если модуль не разрешен, то работать не будет. В разных архитектурах по разному делают. Как в ST32 я не знаю. Если частота не подведена, например выбран неактивный источник, то работать ничто не будет. В AM3715 надо даже две частоты разрешать для модуля и для интерфейса.
AHTOXA
Цитата(Ешь @ Nov 6 2015, 23:09) *
Поправил, но ничего не поменялось. Так же сейчас задумался, похоже там не должно быть отрицания. В документации сказано, что 1 там ставится когда данные передались, т.е. эта строка так должна выглядить:
Код
while(USART1->ISR & USART_ISR_TXE); //Ждем установки флага TXE - конца передачи данных на сдвиговый регистр

После этой правки, он благополучно завис на этом месте. Видимо все-таки дело в том, что ещё нужно что-то инициализировать...

Нет, этот флаг взводится, когда регистр передатчика пуст, и в него можно записывать. Поэтому отрицание убирать не надо.
Может, у вас просто скорость не совпадает? Вы осциллографом не смотрели на ножке TX?
И ещё один момент. Попробуйте сначала включить тактирование USART, и уже потом включать альтернативную функцию ножки. По крайней мере, у меня сделано так, и всё работает.

Цитата(Tarbal @ Nov 6 2015, 23:57) *
Если модуль не разрешен, то работать не будет.

Да разрешён у него модуль, вот же строка, которая включает USART1 (даже с комментарием!):
Код
  RCC->APB2ENR |= RCC_APB2ENR_USART1EN; //Включаем тактирование модуля USART1
ViKo
Почему в функции передачи строки передаете символы n и r? Слэши потеряли.
Ешь
Цитата(AHTOXA @ Nov 6 2015, 20:03) *
Может, у вас просто скорость не совпадает? Вы осциллографом не смотрели на ножке TX?

Мне кажется если бы не совпадала скорость, я бы что-то да получал с порта. Но проверил, настройка частоты USARTa и Minicom'a совпадают.
Осциллографа к сожалению под рукой нет, в понедельник попробую промерить. Но померил мультиметром, на ноге 0,9В... Что это означает, пока понять не могу...

Цитата(ViKo @ Nov 7 2015, 07:02) *
Почему в функции передачи строки передаете символы n и r? Слэши потеряли.

За это конечно спасибо, но проблема явно не в слэшах :-(
etoja
Цитата(Ешь @ Nov 6 2015, 19:10) *
Всем привет!
Использую плату STM32L053 Discovery с контроллером STM32L053C8T6, и не могу запустить USART.


CODE
main()
{
SystemInit();
USARTInit();
fput_char((char) 'A');
}
// -----------------------------------------------------------------------------------------------
void USARTInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;

/* USARTx configured as follow:
- BaudRate = 9600 baud
- Word Length = 8 Bits
- One Stop Bit
- No parity
- Hardware flow control disabled (RTS and CTS signals)
- Receive and transmit enabled
*/
USART_InitStructure.USART_BaudRate = 9600;
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;

/* Enable GPIO clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);

/* Enable USART clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

/* Connect PXx to USARTx_Tx */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);
#ifdef UART_TX_ON_PA14
GPIO_PinAFConfig(GPIOA, GPIO_PinSource14, GPIO_AF_1);
#endif

/* Connect PXx to USARTx_Rx */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);

/* Configure USART Tx, Rx as alternate function push-pull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
#ifdef UART_TX_ON_PA14
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14 | GPIO_Pin_10;
#endif
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure);

/* USART configuration */
USART_Init(USART1, &USART_InitStructure);

/* Enable USART */
USART_Cmd(USART1, ENABLE);

}
// -----------------------------------------------------------------------------------------------
void fput_char(char ch)
{
/* write a character to the USART */
USART_SendData(USART1, (uint8_t) ch);
/* Loop until transmit data register is empty */
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)
{}
}
// -----------------------------------------------------------------------------------------------
Ешь
etoja, спасибо, но удалось решить проблему без использование библиотеки, на уровне регистров. (Кстати, откуда взять StdPeriphLib для STM32L0xx??? Я вот не нашел нигде.)

За решение спасибо компании ST, которая на странице микроконтроллера выложила сниппеты, среди которых я нашел код для работы с USART (там работа именно с регистрами).
Правда пока не вникал в него и не могу сказать где именно я ошибся. Как пойму где была ошибка в моем коде отпишусь.
Ниже приведу пример кода, который у меня заработал прямо сразу.

CODE

/**
******************************************************************************
* File 01_Transmitter/main.c
* Author MCD Application Team
* Version V1.1.1
* Date 04-March-2015
* Brief This code example shows how to configure the GPIOs and USART1
* in order to send bytes.
*
==============================================================================
##### RCC specific features #####
==============================================================================
[..] After reset the device is running from MSI (2 MHz) with Flash 0 WS,
and voltage scaling range is 2 (1.5V)
all peripherals are off except internal SRAM, Flash and SW-DP.
(+) There is no prescaler on High speed (AHB) and Low speed (APB) busses;
all peripherals mapped on these busses are running at MSI speed.
(+) The clock for all peripherals is switched off, except the SRAM and
FLASH.
(+) All GPIOs are in analog state, except the SW-DP pins which
are assigned to be used for debug purpose.
[..] Once the device started from reset, the user application has to:
(+) Configure the clock source to be used to drive the System clock
(if the application needs higher frequency/performance)
(+) Configure the System clock frequency and Flash settings
(+) Configure the AHB and APB busses prescalers
(+) Enable the clock for the peripheral(s) to be used
(+) Configure the clock source(s) for peripherals whose clocks are not
derived from the System clock (ADC, RTC/LCD, RNG and IWDG)
===============================================================================
##### MCU Resources #####
===============================================================================
- RCC
- GPIO PA9(USART1_TX),PA10(USART1_RX),PA0,PA5,PB4
- USART1
- EXTI

===============================================================================
##### How to use this example #####
===============================================================================
- this file must be inserted in a project containing the following files :
o system_stm32l0xx.c, startup_stm32l053xx.s
o stm32l0xx.h to get the register definitions
o CMSIS files
===============================================================================
##### How to test this example #####
===============================================================================
- Plug cable " USB to TTL 3V3 " (from FTDIChip), to GND, PA9 and PA10.
- Launch serial communication SW on PC
- Launch the program
- Press the user button
- "ST" is transmit to PC
- The green LED should blink if everything goes well
(transmit request)
*
******************************************************************************
* Attention
*
* <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/

/* Includes ------------------------------------------------------------------*/
#include "stm32l0xx.h"

/** STM32L0_Snippets
*
*/

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Time-out values */
#define HSI_TIMEOUT_VALUE ((uint32_t)100) /* 100 ms */
#define PLL_TIMEOUT_VALUE ((uint32_t)100) /* 100 ms */
#define CLOCKSWITCH_TIMEOUT_VALUE ((uint32_t)5000) /* 5 s */

/* Delay value : short one is used for the error coding, long one (~1s) in case
of no error or between two bursts */
#define SHORT_DELAY 200
#define LONG_DELAY 1000

/* Error codes used to make the red led blinking */
#define ERROR_USART_TRANSMIT 0x01
#define ERROR_HSI_TIMEOUT 0x02
#define ERROR_PLL_TIMEOUT 0x03
#define ERROR_CLKSWITCH_TIMEOUT 0x04

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static __IO uint32_t Tick;
volatile uint16_t error = 0; //initialized at 0 and modified by the functions

uint8_t send = 0;
const uint8_t stringtosend[] = "ST\n";

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
void Configure_GPIO_LED(void);
void Configure_GPIO_USART1(void);
void Configure_USART1(void);
void Configure_GPIO_Button(void);
void Configure_EXTI(void);

/* Private functions ---------------------------------------------------------*/

/**
* Brief Main program.
* Param None
* Retval None
*/
int main(void)
{
/*!< At this stage the microcontroller clock setting is already configured,
this is done through SystemInit() function which is called from startup
file (startup_stm32l0xx.s) before to branch to application main.
To reconfigure the default setting of SystemInit() function, refer to
system_stm32l0xx.c file
*/
SysTick_Config(2000); /* 1ms config */
SystemClock_Config();
Configure_GPIO_LED();
if (error != 0)
{
while(1) /* endless loop */
{
}
}

SysTick_Config(16000); /* 1ms config */

Configure_GPIO_USART1();
Configure_USART1();
Configure_GPIO_Button();
Configure_EXTI();

/* Start transmission in button IRQ handler */
while (1) /* Infinite loop */
{
}
}


/**
* Brief This function configures the system clock @16MHz and voltage scale 1
* assuming the registers have their reset value before the call.
* POWER SCALE = RANGE 1
* SYSTEM CLOCK = PLL MUL8 DIV2
* PLL SOURCE = HSI/4
* FLASH LATENCY = 0
* Param None
* Retval None
*/
__INLINE void SystemClock_Config(void)
{
uint32_t tickstart;
/* (1) Enable power interface clock */
/* (2) Select voltage scale 1 (1.65V - 1.95V)
i.e. (01) for VOS bits in PWR_CR */
/* (3) Enable HSI divided by 4 in RCC-> CR */
/* (4) Wait for HSI ready flag and HSIDIV flag */
/* (5) Set PLL on HSI, multiply by 8 and divided by 2 */
/* (6) Enable the PLL in RCC_CR register */
/* (7) Wait for PLL ready flag */
/* (8) Select PLL as system clock */
/* (9) Wait for clock switched on PLL */
RCC->APB1ENR |= (RCC_APB1ENR_PWREN); /* (1) */
PWR->CR = (PWR->CR & ~(PWR_CR_VOS)) | PWR_CR_VOS_0; /* (2) */

RCC->CR |= RCC_CR_HSION | RCC_CR_HSIDIVEN; /* (3) */
tickstart = Tick;
while ((RCC->CR & (RCC_CR_HSIRDY |RCC_CR_HSIDIVF)) != (RCC_CR_HSIRDY |RCC_CR_HSIDIVF)) /* (4) */
{
if ((Tick - tickstart ) > HSI_TIMEOUT_VALUE)
{
error = ERROR_HSI_TIMEOUT; /* Report an error */
return;
}
}
RCC->CFGR |= RCC_CFGR_PLLSRC_HSI | RCC_CFGR_PLLMUL8 | RCC_CFGR_PLLDIV2; /* (5) */
RCC->CR |= RCC_CR_PLLON; /* (6) */
tickstart = Tick;
while ((RCC->CR & RCC_CR_PLLRDY) == 0) /* (7) */
{
if ((Tick - tickstart ) > PLL_TIMEOUT_VALUE)
{
error = ERROR_PLL_TIMEOUT; /* Report an error */
return;
}
}
RCC->CFGR |= RCC_CFGR_SW_PLL; /* (8) */
tickstart = Tick;
while ((RCC->CFGR & RCC_CFGR_SWS_PLL) == 0) /* (9) */
{
if ((Tick - tickstart ) > CLOCKSWITCH_TIMEOUT_VALUE)
{
error = ERROR_CLKSWITCH_TIMEOUT; /* Report an error */
return;
}
}
}


/**
* Brief This function enables the peripheral clocks on GPIO port A and B,
* configures GPIO PB4 in output mode for the Green LED pin,
* configures GPIO PA5 in output mode for the Red LED pin,
* Param None
* Retval None
*/
__INLINE void Configure_GPIO_LED(void)
{
/* (1) Enable the peripheral clock of GPIOA and GPIOB */
/* (2) Select output mode (01) on GPIOA pin 5 */
/* (3) Select output mode (01) on GPIOB pin 4 */
RCC->IOPENR |= RCC_IOPENR_GPIOAEN | RCC_IOPENR_GPIOBEN; /* (1) */
GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODE5))
| (GPIO_MODER_MODE5_0); /* (2) */
GPIOB->MODER = (GPIOB->MODER & ~(GPIO_MODER_MODE4))
| (GPIO_MODER_MODE4_0); /* (3) */
}

/**
* Brief This function :
- Enables GPIO clock
- Configures the USART1 pins on GPIO PA9 PA10
* Param None
* Retval None
*/
__INLINE void Configure_GPIO_USART1(void)
{
/* Enable the peripheral clock of GPIOA */
RCC->IOPENR |= RCC_IOPENR_GPIOAEN;

/* GPIO configuration for USART1 signals */
/* (1) Select AF mode (10) on PA9 and PA10 */
/* (2) AF4 for USART1 signals */
GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODE9|GPIO_MODER_MODE10))\
| (GPIO_MODER_MODE9_1 | GPIO_MODER_MODE10_1); /* (1) */
GPIOA->AFR[1] = (GPIOA->AFR[1] &~ (0x00000FF0))\
| (4 << (1 * 4)) | (4 << (2 * 4)); /* (2) */
}

/**
* Brief This function configures USART1.
* Param None
* Retval None
*/
__INLINE void Configure_USART1(void)
{
/* Enable the peripheral clock USART1 */
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;

/* Configure USART1 */
/* (1) oversampling by 16, 9600 baud */
/* (2) 8 data bit, 1 start bit, 1 stop bit, no parity */
USART1->BRR = 160000 / 96; /* (1) */
USART1->CR1 = USART_CR1_TE | USART_CR1_UE; /* (2) */

/* polling idle frame Transmission */
while((USART1->ISR & USART_ISR_TC) != USART_ISR_TC)
{
/* add time out here for a robust application */
}
USART1->ICR |= USART_ICR_TCCF;/* clear TC flag */
USART1->CR1 |= USART_CR1_TCIE;/* enable TC interrupt */

/* Configure IT */
/* (3) Set priority for USART1_IRQn */
/* (4) Enable USART1_IRQn */
NVIC_SetPriority(USART1_IRQn, 0); /* (3) */
NVIC_EnableIRQ(USART1_IRQn); /* (4) */
}

/**
* Brief This function :
- Enables GPIO clock
- Configures the Push Button GPIO PA0
* Param None
* Retval None
*/
__INLINE void Configure_GPIO_Button(void)
{
/* Enable the peripheral clock of GPIOA */
RCC->IOPENR |= RCC_IOPENR_GPIOAEN;

/* Select mode */
/* Select input mode (00) on PA0 */
GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODE0));
}

/**
* Brief This function configures EXTI.
* Param None
* Retval None
*/
__INLINE void Configure_EXTI(void)
{
/* Configure Syscfg, exti and nvic for pushbutton PA0 */
/* (1) PA0 as source input */
/* (2) Unmask port 0 */
/* (3) Rising edge */
/* (4) Set priority */
/* (5) Enable EXTI0_1_IRQn */
SYSCFG->EXTICR[0] = (SYSCFG->EXTICR[0] & ~SYSCFG_EXTICR1_EXTI0) | SYSCFG_EXTICR1_EXTI0_PA; /* (1) */
EXTI->IMR |= EXTI_IMR_IM0; /* (2) */
EXTI->RTSR |= EXTI_RTSR_TR0; /* (3) */
NVIC_SetPriority(EXTI0_1_IRQn, 0); /* (4) */
NVIC_EnableIRQ(EXTI0_1_IRQn); /* (5) */
}

/******************************************************************************/
/* Cortex-M0 Plus Processor Exceptions Handlers */
/******************************************************************************/

/**
* Brief This function handles NMI exception.
* Param None
* Retval None
*/
void NMI_Handler(void)
{
}

/**
* Brief This function handles Hard Fault exception.
* Param None
* Retval None
*/
void HardFault_Handler(void)
{
/* Go to infinite loop when Hard Fault exception occurs */
while (1)
{
}
}

/**
* Brief This function handles SVCall exception.
* Param None
* Retval None
*/
void SVC_Handler(void)
{
}

/**
* Brief This function handles PendSVC exception.
* Param None
* Retval None
*/
void PendSV_Handler(void)
{
}

/**
* Brief This function handles SysTick Handler.
* It toggles the green led if the action has been performed correctly
* and toggles the red led coding the error number
* Param None
* Retval None
*/
void SysTick_Handler(void)
{
static uint32_t long_counter = LONG_DELAY;
static uint32_t short_counter = SHORT_DELAY;
static uint16_t error_temp = 0;

Tick++;
if (long_counter-- == 0)
{
if(error == 0)
{
/* the following instruction can only be used if no ISR modifies GPIOC ODR
either by writing directly it or by using GPIOC BSRR or BRR
else a toggle mechanism must be implemented using GPIOC BSRR and/or BRR
*/
GPIOB->ODR ^= (1 << 4);//toggle green led on PB4
long_counter = LONG_DELAY;
}
else if (error != 0xFF)
{
/* red led blinks according to the code error value */
error_temp = (error << 1) - 1;
short_counter = SHORT_DELAY;
long_counter = LONG_DELAY << 1;
GPIOA->BSRR = (1 << 5); //set red led on PA5
GPIOB->BRR = (1 << 4); //switch off green led on PB4
}
}
if (error_temp > 0)
{
if (short_counter-- == 0)
{
GPIOA->ODR ^= (1 << 5); //toggle red led
short_counter = SHORT_DELAY;
error_temp--;
}
}
}


/******************************************************************************/
/* STM32L0xx Peripherals Interrupt Handlers */
/* Add here the Interrupt Handler for the used peripheral(s) (PPP), for the */
/* available peripheral interrupt handler's name please refer to the startup */
/* file (startup_stm32l0xx.s). */
/******************************************************************************/


/**
* Brief This function handles EXTI 0 1 interrupt request.
* Param None
* Retval None
*/
void EXTI0_1_IRQHandler(void)
{
if((EXTI->PR & EXTI_PR_PR0) == EXTI_PR_PR0)
{
/* Clear EXTI 0 flag */
EXTI->PR |= EXTI_PR_PR0;

/* start USART transmission */
USART1->TDR = stringtosend[send++]; /* Will inititiate TC if TXE */
}
}

/**
* Brief This function handles USART1 interrupt request.
* Param None
* Retval None
*/
void USART1_IRQHandler(void)
{
if((USART1->ISR & USART_ISR_TC) == USART_ISR_TC)
{
if(send == sizeof(stringtosend))
{
send=0;
USART1->ICR |= USART_ICR_TCCF; /* Clear transfer complete flag */
GPIOB->ODR ^= (1 << 4); /* Toggle green led on PB4 */
}
else
{
/* clear transfer complete flag and fill TDR with a new char */
USART1->TDR = stringtosend[send++];
}
}
else
{
error = ERROR_USART_TRANSMIT; /* Report an error */
NVIC_DisableIRQ(USART1_IRQn); /* Disable USART1_IRQn */
}

}


/************************ © COPYRIGHT STMicroelectronics *****END OF FILE****/

KnightIgor
Цитата(Ешь @ Nov 8 2015, 20:37) *
За решение спасибо компании ST, которая на странице микроконтроллера выложила сниппеты, среди которых я нашел код для работы с USART (там работа именно с регистрами).
Правда пока не вникал в него и не могу сказать где именно я ошибся. Как пойму где была ошибка в моем коде отпишусь.

У меня в коде есть такой комментарий самому себе. Как я это раскопал, уже не помню:
Код
    // NOTE! - bits USART_CR3_OVRDIS and USART_CR3_ONEBIT can be set only
    // if UART is yet disabled.
    STDIO_DEVICE->CR3 |= USART_CR3_EIE | USART_CR3_OVRDIS | USART_CR3_ONEBIT;
    USART_ENABLE(STDIO_DEVICE);

Может и у Вас порядок инициализации не учитывал эту особенность?

P.S. Глянул код от ТС. Я имею ввиду, что, может,
Код
USART1->CR1 |= USART_CR1_UE; //Включаем USART1

надо перенести в конец инициализации?
Ешь
Цитата(KnightIgor @ Nov 9 2015, 13:21) *
надо перенести в конец инициализации?

Как оказалось, проблема не в этом.

В общем нашел две ошибки, которые исправил и все заработало.
Первая ошибка идиотская. Как я этого раньше не заметил до сих пор не пойму 05.gif Clock порта в этом контроллере запускается не в регистре AHBENR, а в регистре IOPENR. Соответственно должно быть не так:
Код
RCC->AHBENR |= RCC_IOPENR_GPIOAEN; //Включаем тактирование порта А

А так:
Код
RCC->IOPENR |= RCC_IOPENR_GPIOAEN; //Включаем тактирование порта А

И вторая.
Нужно было исправить эту строку:
Код
GPIOA->MODER |= GPIO_MODER_MODE9_1; //PA9 - выход AF

Вот так:
Код
GPIOA->MODER = (GPIOA->MODER & ~GPIO_MODER_MODE9)|(GPIO_MODER_MODE9_1); //PA9 - выход AF

То есть нужно было не просто поместить 1 в 18 бит, а в явном виде поместить 0 в 19 бит, а 1 в 18.
Вторая ошибка оказалось для меня весьма неожиданной. Так как я думал, что все биты по умолчанию нули. Но без этих исправлений у меня ничего не заработало.

P.S. Код с исправлениями:
CODE

#include "stm32l0xx.h" // Device header

void Init(void); //Объявление функции инициализации RCC, GPIO, USART
void Usart1_Transmit(uint8_t); //Объявление функции передачи символа через USART
void Usart1_Transmit_str(char* str); //Объявление функции передачи строки через USART


int main()
{
Init(); //Вызов функции инициализации
while(1)
{
Usart1_Transmit_str("STM32L-DISCOVERY"); //Вызов функции передачи строки через USART
for(uint32_t i=0; i<0x002FFFFF; i++); //Временная задержка
}
}

void Init()
{
//RCC
RCC->CR |= RCC_CR_HSION; //Включаем тактовый генератор HSI
while(!(RCC_CR_HSIRDY)); //Ждем его стабилизации
RCC->CFGR |= RCC_CFGR_SW_HSI; //Выбираем источником тактовой частоты SYSCLK генератор HSI
RCC->CR &= ~RCC_CR_MSION; //Отключаем генератор MSI.

//GPIO
RCC->IOPENR |= RCC_IOPENR_GPIOAEN; //Включаем тактирование порта А
GPIOA->MODER = (GPIOA->MODER & ~GPIO_MODER_MODE9)|(GPIO_MODER_MODE9_1); //PA9 - выход AF
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_9; //PA9 - выход push-pull
GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPD9); //PA9 - без подтяжки
GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEED9; //PA9 - скорость 40 МГц
/*Далее в разряды AFRH9[3:0] регистра альтернативных функций GPIOA_AFRH записываем
значение 0100, тем самым для вывода PA9 задаем значение
альтернативной функции - AF4, что соответствует USART1_TX*/
GPIOA->AFR[1] |= (0x4<<4);

//USART1
RCC->APB2ENR |= RCC_APB2ENR_USART1EN; //Включаем тактирование модуля USART1
USART1->CR1 |= USART_CR1_UE; //Включаем USART1
USART1->CR1 &= ~USART_CR1_M; //Длина слова - 8 бит
USART1->CR2 &= ~USART_CR2_STOP; //1 стоп-бит
USART1->BRR = 0x683; //baud rate 9600 при частоте HSI = 16 МГц
USART1->CR1 |= USART_CR1_TE; //Разрешаем передачу данных
}

//Функци передачи символа через USART
void Usart1_Transmit(uint8_t data)
{
while(!(USART1->ISR & USART_ISR_TC)); //Ждем установки флага TC - завершения передачи
USART1->TDR = data;
}

//Функция передачи строки через USART
void Usart1_Transmit_str(char* str)
{
uint8_t i=0;
while(str[i])
{
Usart1_Transmit(str[i]);
i++;
}
Usart1_Transmit('\n');
Usart1_Transmit('\r');
}
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.