Elektronik yazılım ile ilgilenen bir çok kişi en azından bir kaç kere iki işlemciyi veya işlemci ile bilgisayarı haberleştirmek ihtiyacı hissetmiştir. Bu yazımızda iki adet Stm32f4 kartını birbiri ile USART üzerinden haberleştireceğiz.
Normalde bu örneği yapmayacaktım ancak bir arkadaşım rica ettiği için paylaşıyorum. Örnek kolay bir örnek olabilir, ama bir çok kişinin işine yarayacaktır.
Öncelikle haberleşme için bir çok yöntem kullanabilirdik, örneğin; Bluetooth, SPI, I2C, USART, RF, Ethernet vb örnekleri çoğaltabiliriz. Ancak bizim kitimizde USART dahili olarak bulunduğu için bu haberleşmeyi tercih ettik.
O halde kod yazmaya geçebiliriz.
Bu yazıda her iki kart da birbirine veri gönderebilir.
#include "stm32f4xx.h" //stm32f4 kütüphanesi
#include "stm32f4xx_gpio.h" //GPIO kütüphanesi
#include "stm32f4xx_rcc.h" // RCC clock kütüphanesi
#include "stm32f4xx_usart.h" // usart kütüphanesi
/********************************************************************************/
void GPIO_Init(void);
void USART_Init(void);
void GPIO_Init(void);
void USART_Init(void);
/********************************************************************************/
/********************************************************************************/
/* Gerekli değişken tanımlamaları */
unsigned char Device_ID = 1;
unsigned char Rx_Data[10];
unsigned char Tx_Data[10];
unsigned char gelen_data_sayaci= 0;
unsigned char Gelen_veri=0;
/********************************************************************************/
/* Gerekli değişken tanımlamaları */
unsigned char Device_ID = 1;
unsigned char Rx_Data[10];
unsigned char Tx_Data[10];
unsigned char gelen_data_sayaci= 0;
unsigned char Gelen_veri=0;
/********************************************************************************/
/* Led için konfigürasyon ayarlamaları */
void GPIO_Init(void)
{
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure; // Port yönlendirmesi
/* Kart üzerindeki butonu giriş olarak tanımladık */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; //Pinler cikis olarak belirlendi
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* PD12, 13, 14 ve PD15 pinleri kullan1lacak */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //Pinler cikis olarak belirlendi
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure);
}
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure; // Port yönlendirmesi
/* Kart üzerindeki butonu giriş olarak tanımladık */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; //Pinler cikis olarak belirlendi
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* PD12, 13, 14 ve PD15 pinleri kullan1lacak */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //Pinler cikis olarak belirlendi
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure);
}
/* USART1 ayarlamaları */
/* usart kesmesi de ayarlandı. gelen data direkt olarak kesme fonksiyonu ile alınacaktır */
void USART_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// GPIO ALTERNATE FUNCTION olarak tanimlanan pinin konfigürasyonlari
// pin ile baglantı kuracagi modül belirlenir.
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_USART1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_USART1);
// USART1 Reset
USART_DeInit(USART1);
// USART konfigürasyonlari:
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_HardwareFlowControl= USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_Init(USART1, &USART_InitStructure);
USART_ITConfig(USART1, USART_IT_RXNE,ENABLE);
// NVIC Init
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
USART_Cmd(USART1, ENABLE);
}
/* usart kesmesi de ayarlandı. gelen data direkt olarak kesme fonksiyonu ile alınacaktır */
void USART_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// GPIO ALTERNATE FUNCTION olarak tanimlanan pinin konfigürasyonlari
// pin ile baglantı kuracagi modül belirlenir.
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_USART1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_USART1);
// USART1 Reset
USART_DeInit(USART1);
// USART konfigürasyonlari:
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_HardwareFlowControl= USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_Init(USART1, &USART_InitStructure);
USART_ITConfig(USART1, USART_IT_RXNE,ENABLE);
// NVIC Init
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
USART_Cmd(USART1, ENABLE);
}
int main(void)
{
GPIO_Init();
USART_Init();
/* Bütün ayarlamaları yaptık. Butona bastığımızda diğer karta veri gönderecek. Hatta bunu bir dizi paketi halinde gönderecek. Bu kartımızın kimlik bilgisi 1 olsun. diğer kartın 2.
*/
while(1)
{
if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)) { while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)); //Butondan çekilene kadar bekle
{
GPIO_Init();
USART_Init();
/* Bütün ayarlamaları yaptık. Butona bastığımızda diğer karta veri gönderecek. Hatta bunu bir dizi paketi halinde gönderecek. Bu kartımızın kimlik bilgisi 1 olsun. diğer kartın 2.
*/
while(1)
{
if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)) { while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)); //Butondan çekilene kadar bekle
Tx_Data[0] = 1; //kimlik bilgimiz 1
Tx_Data[1] = 41;// Gidecek veri, Bunu A harfi olarak da yazabilirsiniz ancak tek karakter olması gerek
// Tx_Data[1] = 'A'; // String bir karakter için böyle de gönderebilirsiniz
USART_SendData(USART1, Tx_Data[0]);
USART_SendData(USART1, Tx_Data[1]);
// İki Datamızı da gönderdik
}
if(Gelen_veri == 41)
{
GPIO_SetBits(GPIOD,GPIO_Pin_12);
{
else
{
GPIO_ResetBits(GPIOD,GPIO_Pin_12);
}
}
}
/********************************************************************************/
/* USART1 KESME FONKSİYONU */
void USART1_IRQHandler(void)
{
if( USART_GetITStatus(USART1, USART_IT_RXNE) )
{
USART_ClearITPendingBit(USART1, USART_IT_RXNE);//kesme bayrağı temizlenir
/* eğer USART biriminden herhangi bir veri gelirse bu fonksiyona girecektir*/
// Gelen veriyi okuma işlemi
Rx_Data[gelen_data_sayaci] = USART_ReceiveData(USART1);
/* USART1 KESME FONKSİYONU */
void USART1_IRQHandler(void)
{
if( USART_GetITStatus(USART1, USART_IT_RXNE) )
{
USART_ClearITPendingBit(USART1, USART_IT_RXNE);//kesme bayrağı temizlenir
/* eğer USART biriminden herhangi bir veri gelirse bu fonksiyona girecektir*/
// Gelen veriyi okuma işlemi
Rx_Data[gelen_data_sayaci] = USART_ReceiveData(USART1);
// Gelen paketteki data sayacini arttir
gelen_data_sayaci++;
/* Bize gelen verinin 2 adet olduğunu varsayıyoruz, bu yüzden aşağıdaki gibi bir işlem yapıyoruz */
if(gelen_data_sayaci == 2)
{
if(Rx_Data[0]== 1) // Yani bizim kimilik bilgimiz ile eşleşiyor ise
{
Gelen_veri = Rx_Data[1];
gelen_data_sayaci = 0; //Yeni gelecek veri paketi için sayacı sıfırla
}
}
else if( USART_GetITStatus(USART1, USART_IT_TXE) )
{
USART_ClearITPendingBit(USART1, USART_IT_TXE);
}
}
Bu kodu her iki karta da yüklediğinizde, birinin butonuna basarsanız diğerinin PD12 ledi yanacaktır. aynı şekilde diğerinin butonuna bastığınızda ilk kartın ledi yanacaktır. Bu örnek üzerinde ufak oynamalar yaparak değişik işlemlerde kullanabilirsiniz.
NOT: Birinci kartın TX pinini diğer kartın Rx pinine, Birinci kartın RX pinini diğer kartın Tx pinine bağlamalısınız. Ayrıca iki kartın GND pinleri de birbirine bağlanmalıdır. Yani birinci kartın PB6 pinini diğer kartın PB7 pinine, yine birinci kartın PB7 pinini diğer kartın PB6 pinine bağlamalısınız.
İyi Çalışmalar