Stm32'de kesme ile sıralı veri alma

Başlatan robikod, 25 Ağustos 2017, 13:21:28

robikod

Merhaba,

Python tarafında slider ile değişen 4 açı değerim var, bu değerler bir dizi içerisinde seri porttan sırayla gönderiliyor.
İlk slider->30 ise ve diğerleri 0 ise de gönderiliyor. Stm tarafında kesme olan kısımdaki kodlarım şu şekilde: (Değişkenleri yukarda tanımlı sadece kod bloğunu atıyorum)

void USART1_IRQHandler(void)
{

  
    if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    {
 
        if ((rx_data != '\n') && (cnt < MAX_STRLEN))
        { //rx_data boş karakter değil ve maximum karakter sayısı aşılması ise
            data[cnt] = rx_data;
            cnt++;
        }
        else
        { // boş karakter gelmemiş ve maksimum karakter kullanılmışsa

            cnt = 0;
        }

        USART_ClearITPendingBit(USART1, USART_IT_RXNE);
    }
}


Şimdi gelelim sorunda, Pyhton tarafından aldığım 4 değer sırayla, gelmiyor yani 2. slider'ın hareketini 1. motorda görüyorum aslında böyle olmamalıydı.
Data dizisindeki 4 elemanı aşağıda 4 motora gönderiyorum.
Burada nasıl sırayla alabilirim ?

Kodların tamamı şu şekilde:
#include "main.h"
#include "common.h"
#include "io_periph_defs.h"
#include "conf.h"

// Kanal 2 de 4 tane Chanel var CH1-CH2-CH3-CH4 4 servo kullanacağımızdan kullanımı kolay olacak
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
void USART1_Init(void);
void led_toggle(void);
void servo_change(void);
static uint8_t cnt = 0;

void servo_controller(uint16_t s1, uint16_t s2, uint16_t s3, uint16_t s4);
void angle_convert_dutycyle(uint16_t angl1, uint16_t angl2, uint16_t angl3, uint16_t angl4);
uint16_t dc, dc2, dc3, dc4;
uint16_t srv1, srv2, srv3, srv4;
static unsigned int USART_angle;
//static unsigned int Led_state = 0;
#define MAX_STRLEN 4
volatile char data[MAX_STRLEN + 1];
char Usart_data;

int main()
{
    Usart1_init();

    SysTick_Config(SystemCoreClock / 1000);
    // init_pin(DEBUG_LED_PORT, DEBUG_LED_PIN2, GPIO_Mode_OUT, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_NOPULL);
    // GPIO_ResetBits(DEBUG_LED_PORT, DEBUG_LED_PIN2); // basılmadığı durumda reset durumundadır.
    // Delay(500);
    // GPIO_ResetBits(DEBUG_LED_PORT, DEBUG_LED_PIN);
    SERVO_GPIO_Init();

    SERVO_PWM_Init();

    // init_pin(DEBUG_LED_PORT, DEBUG_LED_PIN, GPIO_Mode_OUT, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_UP); //led bilgileri tanımlandı.

    USART1_IRQHandler();

    while (1)
    {
        // if (data[0] != '\n')
        // {
        //     servo_change();
        // }
        // Delay(500);
    }
}
void SERVO_GPIO_Init(void) // Servo pin ayarları
{
    GPIO_InitTypeDef GPIO_InitStructure;
    //TIM2-PA0
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //TIM2'de CH_1 pini PA0 olduğu için ilk servo ona göre ayarlandı
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource0, GPIO_AF_1); // PA0'ın AF_1 kısmında TIM2 ve CH_1 aktif

    //TIM2-PA1
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; //TIM2 CH_2 PA1'de tanımlı
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_1); // TIM2 ve CH2 bu kısımda tanımlı
    //TIM2-PA2
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //TIM2 CH_3 PA3'de tanımlı
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_1); // TIM2 ve CH3 bu kısımda tanımlı
    //TIM2-PA3

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; //TIM2 CH_2 PA3'de tanımlı
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_1); // TIM2 ve CH2 bu kısımda tanımlı
}

void SERVO_PWM_Init(void) //servo pwm-timer ayarları
{
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

    TIM_TimeBaseStructure.TIM_Period = 19999; //arr degeri
    TIM_TimeBaseStructure.TIM_Prescaler = 84; //PrescalerValue; 84
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;

    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = 1;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    // Kanal Ayarlarını yaptığımız kısım
    //CH1 için
    TIM_OC1Init(TIM2, &TIM_OCInitStructure);
    TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);

    TIM_ARRPreloadConfig(TIM2, ENABLE);

    // TIM2 de Chanel 2 ayarlarını aktif ediyoruz

    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = 2; //CCR_Val;

    TIM_OC2Init(TIM2, &TIM_OCInitStructure);

    TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);

    TIM_Cmd(TIM2, ENABLE);
    //CH3
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = 3; //CCR_Val;
    TIM_OC3Init(TIM2, &TIM_OCInitStructure);

    TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable);

    TIM_Cmd(TIM2, ENABLE);
    //CH4
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = 4; //CCR_Val;
    TIM_OC4Init(TIM2, &TIM_OCInitStructure);

    TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Enable);

    TIM_Cmd(TIM2, ENABLE);
}

// void led_toggle()
// {
//     GPIO_SetBits(DEBUG_LED_PORT, DEBUG_LED_PIN);
// }
// void led_off()
// {

//     GPIO_ResetBits(DEBUG_LED_PORT, DEBUG_LED_PIN);
// }
void Usart1_init(void)
{
    // Usart ayarlarını yaptığımız kısım
    GPIO_InitTypeDef GPIO_InitStructure;   // Tx ve Rx ayarları için oluşturduğumuz struct
    USART_InitTypeDef USART_InitStrutcure; // Usart ayarları için oluşturduğumuz struct
    NVIC_InitTypeDef NVIC_InitStructure;   //nvic ayarları için oluşturulan struct
    // USART için Clock ayarlarını yapıyoruz
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

    // Datasheet bilgilerine baktığımızda A9-> TX, A10->RX pinleri olarak kullanılıyor.
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; // 9 ve 10. pinleri belirttik
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure); // A portu olduğunu belirttik

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_7); // datasheetinde USART1 için AF değeri 7 olarak verilmiş
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_7);
    // USART Ayarlamaları
    USART_InitStrutcure.USART_BaudRate = 9600;                  //iletişim hızı
    USART_InitStrutcure.USART_WordLength = USART_WordLength_8b; // kaç bitlik veri gönderileceği bilgisi
    USART_InitStrutcure.USART_Parity = USART_Parity_No;
    USART_InitStrutcure.USART_StopBits = USART_StopBits_1;
    USART_InitStrutcure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStrutcure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;

    USART_Init(USART1, &USART_InitStrutcure);
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
    USART_Cmd(USART1, ENABLE); // Usart Aktif
    //                                                   //Bir kesme oluşturacağımız için kesme ayarlarını yapmamız gerekiyor
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //USART1 in kesmesi olduğunu belirttik
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_Init(&NVIC_InitStructure);
}

void USART1_IRQHandler(void)
{

    // USART_ClearITPendingBit(USART1, USART_IT_RXNE);

    // USART_angle = (unsigned int)USART_ReceiveData(USART1);

    //receive a char
    //    char data = USART_ReceiveData(USART1); //receive a char
    //                                            // char data = USART_ReceiveData(USART1); //receive a char
    //     if (data == '\r' || data == '\n')
    //     {
    //         if (rx_index != 0)
    //         {
    //             memcpy((void *)line_buffer, rx_buffer, rx_index);
    //             line_buffer[rx_index] = 0;
    //             line_valid = 1;
    //             data = (unsigned int)USART_angle;
    //             rx_index = 0;
    //             USART_PutString("data geldi");
    //         }
    //     }
    //     else
    //     {
    //         if (rx_index == LINEMAX)
    //             rx_index = 0;

    //         rx_buffer[rx_index++] = data;
    //     }

    /*
*/

    if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    {
        // char buf[100];

        // uint16_t rx_data = USART_ReceiveData(USART1);
        // sprintf(buf, "Incoming Byte is: %d\r\n", rx_data);
        // USART_PutString(buf);
        if (rx_data = 0xAA)
            GPIO_SetBits(DEBUG_LED_PORT, DEBUG_LED_PIN2);
        else if (rx_data = 0x55)
            GPIO_ResetBits(DEBUG_LED_PORT, DEBUG_LED_PIN2);
        if ((rx_data != '\n') && (cnt < MAX_STRLEN))
        { //rx_data boş karakter değil ve maximum karakter sayısı aşılması ise
            data[cnt] = rx_data;
            cnt++;
        }
        else
        { // boş karakter gelmemiş ve maksimum karakter kullanılmışsa

            cnt = 0;
        }

        USART_ClearITPendingBit(USART1, USART_IT_RXNE);
    }
}
void servo_change(void)
{
    srv1 = data[0];
    srv2 = data[1];
    srv3 = data[2];
    srv4 = data[3];
    servo_controller(srv1, srv2, srv3, srv4);
}
void angle_convert_dutycyle(uint16_t angl1, uint16_t angl2, uint16_t angl3, uint16_t angl4)

{

    char buf[100];
    float tmp1 = ((float)angl1 / 180.0f);
    dc = ((tmp1 + 1.0f) * 1000.0f);
    sprintf(buf, "1.Servo Angle is: %d , DC: %7.2f\r\n", angl1, ((tmp1 + 10.0f) * 100.0f));
    USART_PutString(buf);

    char buf2[100];
    float tmp2 = ((float)angl2 / 180.0f);
    dc2 = ((tmp1 + 1.0f) * 1000.0f);
    sprintf(buf2, "2.Servo Angle is: %d , DC: %7.2f\r\n", angl2, ((tmp2 + 10.0f) * 100.0f));
    USART_PutString(buf2);

    char buf3[100];
    float tmp3 = ((float)angl3 / 180.0f);
    dc3 = ((tmp3 + 1.0f) * 1000.0f);
    sprintf(buf3, "3.Servo Angle is: %d , DC: %7.2f\r\n", angl3, ((tmp3 + 10.0f) * 100.0f));
    USART_PutString(buf3);

    char buf4[100];
    float tmp4 = ((float)angl4 / 180.0f);
    dc4 = ((tmp4 + 1.0f) * 1000.0f);
    sprintf(buf4, "4.Servo Angle is: %d , DC: %7.2f\r\n", angl4, ((tmp4 + 10.0f) * 100.0f));
    USART_PutString(buf4);
}

void servo_controller(uint16_t s1, uint16_t s2, uint16_t s3, uint16_t s4)
{

    angle_convert_dutycyle(s1, s2, s3, s4);
    TIM2->CCR1 = dc;
    Delay(300);
    TIM2->CCR2 = dc2;
    Delay(300);
    TIM2->CCR3 = dc3;
    Delay(300);
    TIM2->CCR4 = dc4;
    Delay(300);
}
static void USART_SendString(USART_TypeDef *USARTx, char *s)
{
    while (*s)
    {
        while (!USART_GetFlagStatus(USARTx, USART_FLAG_TC))
            ;
        USART_SendData(USARTx, *s);
        s++;
    }
}

void USART_PutString(char *s)
{
    // Send a string
    while (*s)
    {
        USART_PutChar(*s++);
    }
}
void USART_PutChar(char c)
{
    // Wait until transmit data register is empty
    while (!USART_GetFlagStatus(USART1, USART_FLAG_TXE))
        ;
    // Send a char using USART1
    USART_SendData(USART1, c);
}



robikod

Sorunu çözdüm. Merak eden olursa nasıl olduğunu açıklayabilirim

MC_Skywalker

Merak eden olursa nasıl olduğunu açıklayabilirm ne demek?




baran123

Pakete ekleyip alman daha doğru olur.
[X][Y][4 BYTE DATA][Z]
burada x, y, z senin belirlediğin sabit bir karakter.
Alıcı tarafta
x geldiyse y yi bekle
y geldiyse 4 byte al
ve z yi bekle
şeklinde olabilir.

robikod

Alıntı yapılan: MC_Skywalker - 25 Ağustos 2017, 20:24:40
Merak eden olursa nasıl olduğunu açıklayabilirm ne demek?
Cevap yazan olmadığına göre, ilgilenen olmadığını düşündüm ama aynı sorunu yaşayan olursa açıklarım demek

robikod

Alıntı yapılan: baran123 - 25 Ağustos 2017, 20:30:52
Pakete ekleyip alman daha doğru olur.
[X][Y][4 BYTE DATA][Z]
burada x, y, z senin belirlediğin sabit bir karakter.
Alıcı tarafta
x geldiyse y yi bekle
y geldiyse 4 byte al
ve z yi bekle
şeklinde olabilir.

Dizi olarak aldığım için. Python tarafında dizi sayısını 1 artırıp, son diziyi boş tanımladığımda hata düzeldi.
Peki bu şekilde bir paketi nasıl tanımlayabilirim ? Tam olarak bilgim yok, bu yöntemin bir adı var mı ?

baran123

#6
Bu standart bir paketlemedir.
Haberleşme protokollerinin hepsinde veriler paketlenir.
Başın sabit bir karakter koyarsınız bu karakter gelince tamam benim verilerim geliyor diyebilirsiniz.
Verileri aldıktan sonra sonunda ise yine sabit bir karakterle verinin bittiğini anlarsınız.
Böylece hem verinin güvenliği bir puan artmış olur hemde kendi haberleşme katmanınızı tasarlamış olursunuz.
Bu yapıya geliştiren ise paket içerisine "CheckSum, CRC" tarzı kontroller eklemektir.

Bunu kullanmazsanız ne olur ona bakalım.
ROBOT kelimesini göndereceksiniz.
Verici yolluyor.
Fakat alan taraf bir problemden dolayı ilk karakteri alamadı ve gecikti, ne olur ?
OBOT olarak okuduğunuz veriyi yanlış değerlendirirsiniz ve problem oluşur.

Bu yüzden önce sabit 2 tane karakter yollanır
[X][Y] olsun bunlar
Sonra verinin uzunluğu yollansın (Daha iyi oldu artık veri uzunluğu dinamik)
[L] diyelim bunada.
Sonra L uzunluğunda veri olsun
[ DATA(L) ]
Hadi birde CRC ekleyelim CRC16 olsun
[CRC16] (2 BYTE)
ve son olarak paket sonu karakteri.
[Z] olsun.
[X] [Y] [L BYTE DATA] [CRC16] [Z]

Alıcı taraf artık paketi alıp işler orasını sana bırakıyorum.
Bunu biraz daha geliştirip birde cevap paketi yapabilirsin.
Örneğin veriyi aldım veya alamadım bilgisi.
Hatta alamadıysa tekrar gönder gibi bir yapı daha hoş olur.
vs vs ...

robikod

Alıntı yapılan: baran123 - 28 Ağustos 2017, 09:18:59
Bu standart bir paketlemedir.
Haberleşme protokollerinin hepsinde veriler paketlenir.
Başın sabit bir karakter koyarsınız bu karakter gelince tamam benim verilerim geliyor diyebilirsiniz.
Verileri aldıktan sonra sonunda ise yine sabit bir karakterle verinin bittiğini anlarsınız.
Böylece hem verinin güvenliği bir puan artmış olur hemde kendi haberleşme katmanınızı tasarlamış olursunuz.
Bu yapıya geliştiren ise paket içerisine "CheckSum, CRC" tarzı kontroller eklemektir.

Bunu kullanmazsanız ne olur ona bakalım.
ROBOT kelimesini göndereceksiniz.
Verici yolluyor.
Fakat alan taraf bir problemden dolayı ilk karakteri alamadı ve gecikti, ne olur ?
OBOT olarak okuduğunuz veriyi yanlış değerlendirirsiniz ve problem oluşur.

Bu yüzden önce sabit 2 tane karakter yollanır
[X][Y] olsun bunlar
Sonra verinin uzunluğu yollansın (Daha iyi oldu artık veri uzunluğu dinamik)
[L] diyelim bunada.
Sonra L uzunluğunda veri olsun
[ DATA(L) ]
Hadi birde CRC ekleyelim CRC16 olsun
[CRC16] (2 BYTE)
ve son olarak paket sonu karakteri.
[Z] olsun.
[X] [Y] [L BYTE DATA] [CRC16] [Z]

Alıcı taraf artık paketi alıp işler orasını sana bırakıyorum.
Bunu biraz daha geliştirip birde cevap paketi yapabilirsin.
Örneğin veriyi aldım veya alamadım bilgisi.
Hatta alamadıysa tekrar gönder gibi bir yapı daha hoş olur.
vs vs ...

Çok teşekkürler

robikod

Alıntı yapılan: baran123 - 28 Ağustos 2017, 09:18:59
Bu standart bir paketlemedir.
Haberleşme protokollerinin hepsinde veriler paketlenir.
Başın sabit bir karakter koyarsınız bu karakter gelince tamam benim verilerim geliyor diyebilirsiniz.
Verileri aldıktan sonra sonunda ise yine sabit bir karakterle verinin bittiğini anlarsınız.
Böylece hem verinin güvenliği bir puan artmış olur hemde kendi haberleşme katmanınızı tasarlamış olursunuz.
Bu yapıya geliştiren ise paket içerisine "CheckSum, CRC" tarzı kontroller eklemektir.

Bunu kullanmazsanız ne olur ona bakalım.
ROBOT kelimesini göndereceksiniz.
Verici yolluyor.
Fakat alan taraf bir problemden dolayı ilk karakteri alamadı ve gecikti, ne olur ?
OBOT olarak okuduğunuz veriyi yanlış değerlendirirsiniz ve problem oluşur.

Bu yüzden önce sabit 2 tane karakter yollanır
[X][Y] olsun bunlar
Sonra verinin uzunluğu yollansın (Daha iyi oldu artık veri uzunluğu dinamik)
[L] diyelim bunada.
Sonra L uzunluğunda veri olsun
[ DATA(L) ]
Hadi birde CRC ekleyelim CRC16 olsun
[CRC16] (2 BYTE)
ve son olarak paket sonu karakteri.
[Z] olsun.
[X] [Y] [L BYTE DATA] [CRC16] [Z]

Alıcı taraf artık paketi alıp işler orasını sana bırakıyorum.
Bunu biraz daha geliştirip birde cevap paketi yapabilirsin.
Örneğin veriyi aldım veya alamadım bilgisi.
Hatta alamadıysa tekrar gönder gibi bir yapı daha hoş olur.
vs vs ...
Ben yine bir şey soracağım kusura bakmayın.
Stm32 de nasıl bir kod yazmalıyım ki böyle bir data alayım. Örnek bir kod var mı acaba bu paket oluşturmayla ilgili internetten baktım ama bulamadım.

baran123

#9
Gönderen kısmı şöyle yapabilirsin.
Ben masaüstünde yazdığım için böyle yaptım sen bunu uyarla STM ye.
Birde o veri gönderme fonksiyonunu daha güzel yapabilirsin böyle tek tek göndermek yerine __packed edip laps diye yollarsan daha kısa olur.

Bir örnek hazırladım fakat tamamlayamadım acele oldu kusura bakma alıcı kısmıda sen düzeltirsin.
Mantık bu şekilde olacak.

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#define CRC16_POLYNOMIAL        (0xA001)

#define LEN_OF_DATA             (8)
#define START_CHAR1             ('A') // 65
#define START_CHAR2             ('B') // 66
#define END_CHAR                ('C') // 67

typedef struct {
    uint8_t startChar1;
    uint8_t startChar2;
    uint8_t dataLen;
    uint8_t data[LEN_OF_DATA];
    
    union 
    {
        struct {
            uint8_t crcBytes[2];
        };
        struct {
            uint16_t crc;
        };
    };
    
    uint8_t endChar;
}DataPacket_TypeDef;

typedef enum {
    PacketState_Wait = 0,
    PacketState_Progress,
    PacketState_Error,       
    PacketState_Completed
}PacketState_TypeDef;

DataPacket_TypeDef Tx_Packet;
DataPacket_TypeDef Rx_Packet;

static PacketState_TypeDef status = PacketState_Wait;
       
void USART_WriteData(uint8_t data);
uint8_t USART_ReadData(void);

void Packet_Init(DataPacket_TypeDef* DataPacket);
void Packet_Send(DataPacket_TypeDef* DataPacket);
void Packet_Show(DataPacket_TypeDef* DataPacket);
uint16_t CRC16_ArrayCalc(uint8_t buf[], uint8_t len);
PacketState_TypeDef Packet_Read(DataPacket_TypeDef* DataPacket, uint8_t rxData);

int main(int argc, char** argv) 
{
    uint8_t dataArray[8] = {0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40};

    uint8_t i;
    for (i = 0; i < LEN_OF_DATA; i++)
        Tx_Packet.data[i] = dataArray[i];
    
    Packet_Init(&Tx_Packet);
    Packet_Send(&Tx_Packet);
    Packet_Show(&Tx_Packet);
    
    uint8_t rxData;
     
    for (;;)
    {
        rxData = USART_ReadData(); // elle karakter girilerek deneyebiliriz.
        
        if (Packet_Read(&Rx_Packet, rxData) == PacketState_Completed)
        {
            Packet_Show(&Rx_Packet);
            
        }
    }
    
    return (0);
}

void USART_WriteData(uint8_t data)
{
    printf("%d\n\r", data);
}

uint8_t USART_ReadData(void)
{
    uint8_t rxData;
    
    scanf("%d", &rxData);
}

void Packet_Init(DataPacket_TypeDef* DataPacket)
{
    DataPacket->startChar1 = START_CHAR1;
    DataPacket->startChar2 = START_CHAR2;
    DataPacket->endChar = END_CHAR;
    DataPacket->dataLen = LEN_OF_DATA;
    DataPacket->crc = CRC16_ArrayCalc(DataPacket->data, DataPacket->dataLen);
}

void Packet_Send(DataPacket_TypeDef* DataPacket)
{
    USART_WriteData(DataPacket->startChar1);
    USART_WriteData(DataPacket->startChar2);
    USART_WriteData(DataPacket->dataLen);

    int i;
    for (i = 0; i < DataPacket->dataLen; i++)
        USART_WriteData(DataPacket->data[i]);
    
    USART_WriteData(DataPacket->crcBytes[1]);
    USART_WriteData(DataPacket->crcBytes[0]);
    USART_WriteData(DataPacket->endChar);   
}

void Packet_Show(DataPacket_TypeDef* DataPacket)
{
    printf("START CHAR 1 : %d\n\r", DataPacket->startChar1);
    printf("START CHAR 2 : %d\n\r", DataPacket->startChar1);
    printf("LEN OF DATA  : %d\n\r", DataPacket->dataLen);
    
    int i;
    for (i = 0; i < DataPacket->dataLen; i++)
        printf("BYTES[%d] = %d\n\r" ,i ,DataPacket->data[i]);
    
    printf("CRC 16: %04X\n\r", DataPacket->crc);
    
    printf("END CHAR : %d\n\r", DataPacket->endChar);
}

PacketState_TypeDef Packet_Read(DataPacket_TypeDef* DataPacket, uint8_t rxData)
{
    static uint8_t state = 0;
    static uint8_t index = 0;

    switch (rxData)
    {
        case 0:
            if (rxData == START_CHAR1);
            {
                status = PacketState_Progress;
                DataPacket->startChar1 = START_CHAR1;
                index = 0;
                state = 1;
            }
            break;
            
        case 1 :
            if (rxData == START_CHAR2)
            {
                DataPacket->startChar2 = START_CHAR2;
                state = 2;
            }        
            break;
            
        case 2:
            DataPacket->dataLen = rxData;
            state = 3;
            break;
            
        case 3:
            if (index != DataPacket->dataLen)
            {
                DataPacket->data[index] = rxData;
                index++;
            }
            else
                state = 4;
            break;
        
        case 4:
            DataPacket->crcBytes[1] = rxData;
            state = 5;
            break;
        
        case 5:
            DataPacket->crcBytes[0] = rxData;
            state = 6;
            break;
        
        case 6:
            if (rxData == END_CHAR)
            {
                DataPacket->endChar = END_CHAR;
                status = PacketState_Completed;
                state = 0;
            }
            else
                status = PacketState_Error;
            break;
    }
}

uint16_t CRC16_ArrayCalc(uint8_t buf[], uint8_t len)
{
    uint16_t crc = 0xFFFF;

    for (uint8_t pos = 0; pos < len; pos++) 
    {
        crc ^= (uint16_t)buf[pos];

        for (uint8_t i = 8; i != 0; i--) 
        {
            if ((crc & 0x0001) != 0) 
            {
                crc >>= 1;
                crc ^= CRC16_POLYNOMIAL;
            }
            else                           
                crc >>= 1;               
        }
    }
    return crc;
}


robikod

#10
Alıntı yapılan: baran123 - 28 Ağustos 2017, 19:03:34
Gönderen kısmı şöyle yapabilirsin.
Ben masaüstünde yazdığım için böyle yaptım sen bunu uyarla STM ye.
Birde o veri gönderme fonksiyonunu daha güzel yapabilirsin böyle tek tek göndermek yerine __packed edip laps diye yollarsan daha kısa olur.

Bir örnek hazırladım fakat tamamlayamadım acele oldu kusura bakma alıcı kısmıda sen düzeltirsin.
Mantık bu şekilde olacak.

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#define CRC16_POLYNOMIAL        (0xA001)

#define LEN_OF_DATA             (8)
#define START_CHAR1             ('A') // 65
#define START_CHAR2             ('B') // 66
#define END_CHAR                ('C') // 67

typedef struct {
    uint8_t startChar1;
    uint8_t startChar2;
    uint8_t dataLen;
    uint8_t data[LEN_OF_DATA];
    
    union 
    {
        struct {
            uint8_t crcBytes[2];
        };
        struct {
            uint16_t crc;
        };
    };
    
    uint8_t endChar;
}DataPacket_TypeDef;

typedef enum {
    PacketState_Wait = 0,
    PacketState_Progress,
    PacketState_Error,       
    PacketState_Completed
}PacketState_TypeDef;

DataPacket_TypeDef Tx_Packet;
DataPacket_TypeDef Rx_Packet;

static PacketState_TypeDef status = PacketState_Wait;
       
void USART_WriteData(uint8_t data);
uint8_t USART_ReadData(void);

void Packet_Init(DataPacket_TypeDef* DataPacket);
void Packet_Send(DataPacket_TypeDef* DataPacket);
void Packet_Show(DataPacket_TypeDef* DataPacket);
uint16_t CRC16_ArrayCalc(uint8_t buf[], uint8_t len);
PacketState_TypeDef Packet_Read(DataPacket_TypeDef* DataPacket, uint8_t rxData);

int main(int argc, char** argv) 
{
    uint8_t dataArray[8] = {0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40};

    uint8_t i;
    for (i = 0; i < LEN_OF_DATA; i++)
        Tx_Packet.data[i] = dataArray[i];
    
    Packet_Init(&Tx_Packet);
    Packet_Send(&Tx_Packet);
    Packet_Show(&Tx_Packet);
    
    uint8_t rxData;
     
    for (;;)
    {
        rxData = USART_ReadData(); // elle karakter girilerek deneyebiliriz.
        
        if (Packet_Read(&Rx_Packet, rxData) == PacketState_Completed)
        {
            Packet_Show(&Rx_Packet);
            
        }
    }
    
    return (0);
}

void USART_WriteData(uint8_t data)
{
    printf("%d\n\r", data);
}

uint8_t USART_ReadData(void)
{
    uint8_t rxData;
    
    scanf("%d", &rxData);
}

void Packet_Init(DataPacket_TypeDef* DataPacket)
{
    DataPacket->startChar1 = START_CHAR1;
    DataPacket->startChar2 = START_CHAR2;
    DataPacket->endChar = END_CHAR;
    DataPacket->dataLen = LEN_OF_DATA;
    DataPacket->crc = CRC16_ArrayCalc(DataPacket->data, DataPacket->dataLen);
}

void Packet_Send(DataPacket_TypeDef* DataPacket)
{
    USART_WriteData(DataPacket->startChar1);
    USART_WriteData(DataPacket->startChar2);
    USART_WriteData(DataPacket->dataLen);

    int i;
    for (i = 0; i < DataPacket->dataLen; i++)
        USART_WriteData(DataPacket->data[i]);
    
    USART_WriteData(DataPacket->crcBytes[1]);
    USART_WriteData(DataPacket->crcBytes[0]);
    USART_WriteData(DataPacket->endChar);   
}

void Packet_Show(DataPacket_TypeDef* DataPacket)
{
    printf("START CHAR 1 : %d\n\r", DataPacket->startChar1);
    printf("START CHAR 2 : %d\n\r", DataPacket->startChar1);
    printf("LEN OF DATA  : %d\n\r", DataPacket->dataLen);
    
    int i;
    for (i = 0; i < DataPacket->dataLen; i++)
        printf("BYTES[%d] = %d\n\r" ,i ,DataPacket->data[i]);
    
    printf("CRC 16: %04X\n\r", DataPacket->crc);
    
    printf("END CHAR : %d\n\r", DataPacket->endChar);
}

PacketState_TypeDef Packet_Read(DataPacket_TypeDef* DataPacket, uint8_t rxData)
{
    static uint8_t state = 0;
    static uint8_t index = 0;

    switch (rxData)
    {
        case 0:
            if (rxData == START_CHAR1);
            {
                status = PacketState_Progress;
                DataPacket->startChar1 = START_CHAR1;
                index = 0;
                state = 1;
            }
            break;
            
        case 1 :
            if (rxData == START_CHAR2)
            {
                DataPacket->startChar2 = START_CHAR2;
                state = 2;
            }        
            break;
            
        case 2:
            DataPacket->dataLen = rxData;
            state = 3;
            break;
            
        case 3:
            if (index != DataPacket->dataLen)
            {
                DataPacket->data[index] = rxData;
                index++;
            }
            else
                state = 4;
            break;
        
        case 4:
            DataPacket->crcBytes[1] = rxData;
            state = 5;
            break;
        
        case 5:
            DataPacket->crcBytes[0] = rxData;
            state = 6;
            break;
        
        case 6:
            if (rxData == END_CHAR)
            {
                DataPacket->endChar = END_CHAR;
                status = PacketState_Completed;
                state = 0;
            }
            else
                status = PacketState_Error;
            break;
    }
}

uint16_t CRC16_ArrayCalc(uint8_t buf[], uint8_t len)
{
    uint16_t crc = 0xFFFF;

    for (uint8_t pos = 0; pos < len; pos++) 
    {
        crc ^= (uint16_t)buf[pos];

        for (uint8_t i = 8; i != 0; i--) 
        {
            if ((crc & 0x0001) != 0) 
            {
                crc >>= 1;
                crc ^= CRC16_POLYNOMIAL;
            }
            else                           
                crc >>= 1;               
        }
    }
    return crc;
}

Çok teşekkür ederim. Gerçekten baya emek vermişsiniz.
Python kısmında gönderdiğim bir dizi var bu 4 açı değerini pyhton'dan alıyorum. Açı değerini pyhton tarafında hex'e çeviriyorum, Stm'e dizi olarak gönderiyorum. Bu değeri duty cycle'a stm tarafında çevirip motorlara gönderiyorum.  Stm32 alıcı taraf olduğundan, rx kullanmam yeterli midir ?