STM32F030F4 инициализируем USART

Набросаю к себе полезных снипетов для STM32F030F4, чтобы самому не забыть и кому-нибудь надеюсь пригодится.

Инициализация USART




Само собой включить тактирование порта A
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);


Для случая когда PA2 — TX, PA3 — RX

void UART_init(void){
    USART_InitTypeDef USART_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
    
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_1);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_1);
    
    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_2 | GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    USART_InitStructure.USART_BaudRate = 115200;
    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(USART1, &USART_InitStructure);
    
    USART_Cmd(USART1, ENABLE);
}


Для случая когда PA9 — TX, PA10 — RX

void UART_init(void){
    USART_InitTypeDef USART_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
    
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);
    
    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_9 | GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    USART_InitStructure.USART_BaudRate = 115200;
    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(USART1, &USART_InitStructure);
    
    USART_Cmd(USART1, ENABLE);
}


Дальше можно слать байты в порт
USART_SendData(USART1, (uint8_t) ch);
  • +1
  • 01 февраля 2016, 00:44
  • aliaksei

Комментарии (19)

RSS свернуть / развернуть
ИМХО, это не снипеты, а «использование SPL». В терминах ST снипетом называется конструкция вида:

/**
  * @brief  This function :
             - Enables GPIO clock
             - Configures the USART1 pins on GPIO PB6 PB7
  * @param  None
  * @retval None
  */
__INLINE void Configure_GPIO_USART1(void)
{
  /* Enable the peripheral clock of GPIOA */
  RCC->AHBENR |= RCC_AHBENR_GPIOAEN;
	
  /* GPIO configuration for USART1 signals */
  /* (1) Select AF mode (10) on PA9 and PA10 */
  /* (2) AF1 for USART1 signals */
  GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODER9|GPIO_MODER_MODER10))\
                 | (GPIO_MODER_MODER9_1 | GPIO_MODER_MODER10_1); /* (1) */
  GPIOA->AFR[1] = (GPIOA->AFR[1] &~ (GPIO_AFRH_AFRH1 | GPIO_AFRH_AFRH2))\
                  | (1 << (1 * 4)) | (1 << (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, reception mode */
  USART1->BRR = 480000 / 96; /* (1) */
  USART1->CR1 = USART_CR1_RXNEIE | USART_CR1_RE | USART_CR1_UE; /* (2) */
  
  /* Configure IT */
  /* (3) Set priority for USART1_IRQn */
  /* (4) Enable USART1_IRQn */
  NVIC_SetPriority(USART1_IRQn, 0); /* (3) */
  NVIC_EnableIRQ(USART1_IRQn); /* (4) */
}

0
Не знал. В моем понимании снипет это полезный кусочек кода. )
0
У st есть примеры которые так называются. Там используется прямое программирование регистров периферии. Поэтому и возникает недопонимание
0
Где их всех посмотреть? Как называются?
0
На вкладке Design Resources для нужного камня можно найти много интересного.
Качать отсюда
0
STM32SnippetsF0
Example Code snippets covering STM32 F0 serie
гугл выкинет прямо на нужную страницу
0
И где смысл в «вариантах», у которых отличие только в 2х цифрах!?
0
Что именно вызвает вопросы?
0
надеюсь, не будете возражать, если докину к вам — рабочий вариант использования PA1 в качестве ноги управления драйвером RS-485

    
  //GPIO
   RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA , ENABLE); //clock GPIOA on
  //PA1 - RS-485 hardware control, USART1_DE
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  GPIO_Init( GPIOA , &GPIO_InitStructure);
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_1);// USART1 DE

  //USART, перед его включением
  //RS-485 driver settings
 USART1->CR3 |=USART_CR3_DEM; //rs-485 driver enable mode
 USART1->CR3 &=~USART_CR3_DEP; //active high
 USART1->CR1 |=USART_CR1_DEDT|USART_CR1_DEAT;

+1
Спасибо.
0
кстати, вы на этом камне с АЦП случайно не работали? а то может поделитесь рабочим кодом…
0
Пока не работал, пытаюсь I2C завести.
0
Кстати, очень рекомендую посмотреть примеры в папке STM32F0xx_StdPeriph_Lib_V1.5.0\Projects\STM32F0xx_StdPeriph_Examples\
0
Спасибо. А это где такое?:) У меня CoIDE 1.7.6 — что-то не нашел
АЦП запустил в первом приближении, вот, если понадобится — код

Пара моментов:
1. В InitADC магические числа из-за того, что SPL не соответствовала даташиту — например, в даташите ADC->CFGR2 включает в себя биты CKMODE[1:0]: ADC clock mode, задающие источник тактирования АЦП (14MHz HSI14 CLK = ADCCLK либо PCLK/2 либо PCLK/4) — в SPL в этом месте радостно находятся

/*******************  Bits definition for ADC_CFGR2 register  *****************/
#define  ADC_CFGR2_JITOFFDIV4 ((uint32_t)0x80000000)       /*!< Jitter Off when ADC clocked by PCLK div4 */
#define  ADC_CFGR2_JITOFFDIV2 ((uint32_t)0x40000000)       /*!< Jitter Off when ADC clocked by PCLK div2 */

и ничего более, что приводит к facepalm`у. А поскольку зарезервированные биты в регистрах АЦП, согласно даташиту, «Reserved, must be kept at reset value» — пришлось посчитать все вручную, на всякий случай.

2. Калибровка АЦП необходима, потому что смещение 0 у stm32f0/1(2?) просто огромное, порядка 66 , и это, к сожалению, так и есть. Зато термодатчик в целом неплох, если усреднять, конечно же. Кстати, калибровка делается при каждом включении АЦП (из спящего режима, например), и при этом АЦП должен быть выключен (Calibration can only be initiated when the ADC is disabled (when ADEN=0)).

Собственно код:


//в моем случае камень работает от HSE=8MHz, SYSCLK=HCLK=PCLK=24MHz

#define ADCAVG	16 //количество усреднений АЦП

//-------------------инициализация периферии------------------------------------------
GPIO_InitTypeDef GPIO_InitStructure;  //инициализируем структуру
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA , ENABLE); //clock GPIOA on
//PA2..3 - ADC inputs
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
  GPIO_Init( GPIOA , &GPIO_InitStructure);

    Vadc=0;
    ADCAverage=ADCAVG;

//-----------------инициализация АЦП и получение данных---------------------------------
void InitADC (void)
{

	ADC_Cmd(ADC1,ENABLE);

	ADC->CCR |= (uint32_t)ADC_CCR_TSEN|ADC_CCR_VREFEN; //temperature sensor enabled & voltage reference
                                                            //enabled

	//тактирование АЦП:
	ADC1->CFGR2 &= (uint32_t) 0x0FFFFFFF; //сброс битов тактирования
	ADC1->CFGR2 |= (uint32_t) 0x40000000; 	//тактирование АЦП: ADCCLK = PCLK/2=12MHz
	//настройка режима
	ADC1->CFGR1 &= (uint32_t) 0x833E0200;	//single mode, right align, soft start, Analog watchdog
                                                //disabled, самый простой режим
	//настройка прерываний
	ADC1->IER 	&= (uint32_t) 0xFFFFFF90; //all interrupts disable

}

uint16_t ADCGetData(uint8_t Cycles)	//получить данные, усредненные по Cycles
{
static uint8_t i;
static uint32_t AdcResult;

	AdcResult=0;

	for (i = 0; i < Cycles; i++)
	{
		//ждем готовности АЦП к преобразованию
		while (ADC_GetFlagStatus(ADC1,ADC_FLAG_ADRDY)==RESET) {continue;};
		//запускаем преобразование
		ADC_StartOfConversion(ADC1);
		//ждем окончания преобразования
		while (ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==RESET) {continue;};
		//и вытаскиваем результат
		AdcResult+=(ADC_GetConversionValue(ADC1)-OffsetAdc);
	}


	//уменьшаем расходы на деление при степенях двойки
	switch (Cycles)
	{
	case 1:
		return (uint16_t)AdcResult;
	break;
	case 2:
		return (uint16_t)(AdcResult>>1);
	break;
	case 4:
		return (uint16_t)(AdcResult>>2);
	break;
	case 8:
		return (uint16_t)(AdcResult>>3);
	break;
	case 16:
		return (uint16_t)(AdcResult>>4);
	break;
	case 32:
		return (uint16_t)(AdcResult>>5);
	break;
	case 64:
		return (uint16_t)(AdcResult>>6);
	break;
	case 128:
		return (uint16_t)(AdcResult>>7);
	break;
	default:
		return (uint16_t)(AdcResult/Cycles);
	break;
	}


}

//----------------------в main`е--------------------------------------------------------
volatile uint8_t OffsetAdc, ADCAverage;
volatile uint16_t Vadc;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //включаем тактирование ADC1

OffsetAdc = ADC_GetCalibrationFactor(ADC1); //калибровка АЦП до его включения!
InitADC();
//ADC_ChannelConfig(ADC1,ADC_CHSELR_CHSEL16,ADC_SMPR1_SMPR_1); //встроенный термодатчик
//ADC_ChannelConfig(ADC1,ADC_CHSELR_CHSEL17,ADC_SMPR1_SMPR_1); //встроенная опора
ADC_ChannelConfig(ADC1,ADC_CHSELR_CHSEL3,ADC_SMPR1_SMPR_1); //PA3, sampling time =13.5 ADC clock cycles

//основной цикл
while (1)

  {
    Vadc=ADCGetData(ADCAverage);
  }

0
0
спасибо большое. тут с CKMODE все хорошо.
0
как вы любите долгие циклы… а мне это совсем не по душе
0
для таких случаев есть уникальная технология — протопотоки. Очень удобно и наглядно
0
да все никак не соберусь раскурить…
do it now, fix later) постоянно не до этого.
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.