COIDE İLE NUCLEO-F401RE PROGRAMLAMA – Usart Uygulaması

Bu yazımızda NUCLEO kitini usart kullanarak bilgisayar ile haberleştireceğiz. Günümüzde neredeyse bütün mikrokontrolörler içerisinde donanımsal usart bulunmaktadır ve kullanımı son derece basittir. Usart pinlerini bilgisayara bağlamak için kullanabileceğiniz bir kaç yöntem vardır. Masaüstü bilgisayar kullanıyorsanız ve bilgisayarınızda rs232 portu varsa (malesef artık pek çok masaüstü bilgisayarda bulunmamakta) max232 benzeri bir gerilim dönüştürücü entegre aracılığı ile usartı bilgisayara bağlayabilirsiniz. Dizüstü bilgisayar kullanıyorsanız yada masaüstü bilgisayarında rs232 portu yoksa bir USB to UART dönüştürücü kullanabilirsiniz. Burada NUCLEO kiti bize bir kolaylık sağlıyor. Daha önce NUCLEO kitinin mbed uyumlu olduğundan bahsetmiştik. Bu sebeple SWD programlama pinlerinin yanısıra, USART2 pinleri de ST-LINK programlayıcı kısmına bağlanmış durumda. Kiti bilgisayarınıza bağladığınızda, aşağıdaki resimde gördüğünüz gibi, otomatik olarak sanal bir com port oluşturuluyor. Böylece USB to UART dönüştürücüye ihtiyacınız kalmıyor.

coide_usart_1

Com port haberleşmesi yapabilmek için öncelikle bir terminal programına ihtiyacınız var. Şu linkten benim kullandığım, gayet kullanışlı özellikleri olan HTerm programını indirebilirsiniz.

Öncelikle ADC örneğimize usart kütüphanesini ekleyerek işe başlıyoruz.

#include "stm32f4xx.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_tim.h"
#include "stm32f4xx_adc.h"
#include "stm32f4xx_usart.h"
uint16_t ADC1ConvertedValue = 0;

void Set_Duty(uint32_t Duty);

int main(void)
{

/* GPIO init */
// LED PIN AYARI
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); // A portunun saat darbesini aktifleştidik.

GPIO_InitTypeDef GPIO_InitStructure;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; // 5 numaralı pin için ayarlıyoruz.
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; // Pin çıkış tipini ayarladık.
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; // Pinimizi output olarak ayarladık.
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; // Pull Up direncini pasif yaptık.
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // Pinin maksimum çalışma frekansını ayarladık.
GPIO_Init(GPIOA, &GPIO_InitStructure); // Ayarları uyguluyoruz.
GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_TIM2);

/*------------------------------------------------------------------------------------------------*/
/* Configure ADC1 Channel0 pin as analog input */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOA, &GPIO_InitStructure);

/*------------------------------------------------------------------------------------------------*/
/* USART GPIO Init */
/* USART2 Tx init (PA2) */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; // 2 numaralı pin için ayarlıyoruz.
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; // Pin çıkış tipini ayarladık.
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; // Pinimizi AF olarak ayarladık.
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; // Pull Up direncini pasif yaptık.
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // Pinin maksimum çalışma frekansını ayarladık.
GPIO_Init(GPIOA, &GPIO_InitStructure); // Ayarları uyguluyoruz.
GPIO_PinAFConfig(GPIOA,GPIO_PinSource2, GPIO_AF_USART2);

/* USART2 Rx init (PA3) */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; // 3 numaralı pin için ayarlıyoruz.
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; // Pin çıkış tipini ayarladık.
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; // Pinimizi AF olarak ayarladık.
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; // Pull Up direncini pasif yaptık.
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // Pinin maksimum çalışma frekansını ayarladık.
GPIO_Init(GPIOA, &GPIO_InitStructure); // Ayarları uyguluyoruz.
GPIO_PinAFConfig(GPIOA,GPIO_PinSource3, GPIO_AF_USART2);

/*------------------------------------------------------------------------------------------------*/
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
/* TIM2 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = (SystemCoreClock / 10000 ) - 1;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

/* Channel 1 Configuration in PWM mode */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;

TIM_OCInitStructure.TIM_Pulse = 0; // Duty değeri
TIM_OC1Init(TIM2, &TIM_OCInitStructure);

/* TIM2 counter enable */
TIM_Cmd(TIM2, ENABLE);

/* TIM2 Main Output Enable */
TIM_CtrlPWMOutputs(TIM2, ENABLE);

/*------------------------------------------------------------------------------------------------*/
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;

/* Enable ADC1 clock so that we can talk to it */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
/* ADC Common Init **********************************************************/
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
ADC_CommonInit(&ADC_CommonInitStructure);

/* ADC1 Init ****************************************************************/
ADC_InitStructure.ADC_Resolution = ADC_Resolution_8b;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 1;
ADC_Init(ADC1, &ADC_InitStructure);

/* ADC1 regular channel0 configuration *************************************/
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_3Cycles);

/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);

/*------------------------------------------------------------------------------------------------*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

USART_InitTypeDef USART_InitStructure;

USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_Init(USART2, &USART_InitStructure);

USART_Cmd(USART2, ENABLE);

while (1)
{
ADC_SoftwareStartConv(ADC1);

/* Test EOC flag */
while ( ADC_GetFlagStatus( ADC1, ADC_FLAG_EOC ) == RESET );

/* Get ADC1 converted data */
ADC1ConvertedValue = ADC_GetConversionValue( ADC1 );

USART_SendData(USART2, ADC1ConvertedValue);

Set_Duty((ADC1ConvertedValue*100) /255); // ADC değerini % olarak ayarladık.

}

}// main sonu.
void Set_Duty(uint32_t Duty)
{
TIM_SetCompare1(TIM2, (Duty * ((SystemCoreClock / 10000 ) - 1)) / 100); // Duty değerini ayarla.
}
 /* USART GPIO Init */
 /* USART2 Tx init (PA2) */
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; // 2 numaralı pin için ayarlıyoruz.
 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; // Pin çıkış tipini ayarladık.
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; // Pinimizi AF olarak ayarladık.
 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; // Pull Up direncini pasif yaptık.
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // Pinin maksimum çalışma frekansını ayarladık.
 GPIO_Init(GPIOA, &GPIO_InitStructure); // Ayarları uyguluyoruz.
 GPIO_PinAFConfig(GPIOA,GPIO_PinSource2, GPIO_AF_USART2);

 /* USART2 Rx init (PA3) */
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; // 3 numaralı pin için ayarlıyoruz.
 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; // Pin çıkış tipini ayarladık.
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; // Pinimizi AF olarak ayarladık.
 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; // Pull Up direncini pasif yaptık.
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // Pinin maksimum çalışma frekansını ayarladık.
 GPIO_Init(GPIOA, &GPIO_InitStructure); // Ayarları uyguluyoruz.
 GPIO_PinAFConfig(GPIOA,GPIO_PinSource3, GPIO_AF_USART2);

Az önce de bahsettiğim gibi USART2 pinleri zaten sanal com portumuza bağlanmış durumda. Bize sadece bu pinleri usart olarak atamak kalıyor.


RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

USART_InitTypeDef USART_InitStructure;

USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_Init(USART2, &USART_InitStructure);

USART_Cmd(USART2, ENABLE);

Pinleri ayarladıktan sonra usart ayarlarını yapıyoruz. Öncelikle usartı çalıştıran saati aktifleştiriyoruz. Haberleşme hızını 9600 baud, datayı da 8 bit, 1 stop biti ve parity olmayacak şekilde ayarlıyoruz. Hem veri almak hemde göndermek istediğimiz için modu tx,rx olarak ayarlıyoruz. Donanım kontrolü yapmayacağımız için none olarak ayarlıyorz.

Ayarlarımız tamamlandı ve veri göndermeye hazırız.


USART_SendData(USART2, ADC1ConvertedValue);

Ana döngümüz içerisinde okuduğumuz ADC verisini usarttan gönderiyoruz.

Programı kite yükledikten sonra HTerm programını açıp gerekli haberleşme ayarlarını yapmanız ve connect butonuna tıklamanız gerekiyor. Bağlantı sağlanınca ekranda akan verilerin potansiyometreyi çevirdiğinizde değiştiğini görebilirsiniz.


while (1)
{
Set_Duty(USART_ReceiveData(USART2)); // USART'tan okuduğumuz veriyi pwm duty olarak ayarladık.
}

Ana döngümüzü bu şekilde düzenlediğimizde bilgisayardan gönderdiğimiz veriyi pwm’e duty olarak atamış olduk. Böylece ledin parlaklığını bilgisayardan 0-100 arası bir sayı göndererek ayarlayabiliriz. Burada dikkat etmemiz gereken terminal programında desimal sayı göndermek için gereken ayarı doğru yapmak. Aşağıdaki resimde kırmızı ile işaretlediğim yerden gönderme kutucuğuna yazdığınız değerin tipini ayarlayabilirsiniz.

coide_USART_2

 

Proje dosyasını linkten indirebilirsiniz. –> coide_USART_uygulamasi_gonderme

Proje dosyasını linkten indirebilirsiniz. –> coide_USART_uygulamasi_alma

Etiket(ler): , , , , , .Yer işareti koy Kalıcı Bağlantı.

Bir Cevap Yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir