STM32F10X Çalışmalarım

Başlatan Mucit23, 12 Mart 2012, 11:17:48

Mucit23

Hall sensörlerle ilgili şöyle bir resim var datasheette.
http://s1.postimg.cc/uul3evqxr/Ekran_Al_nt_s.jpg
Burada yapı gayet net bir şekilde açıklanmış.

Hocam STM32'lerde galiba rotary encoderler kullanarak galiba BLDC motor duğrudan süremiyoruz galiba. Yada bir yolu var ben bilmiyorum.

Bu konuda frescalenin AN notlarına baktım.
http://www.freescale.com/files/dsp/doc/app_note/AN1915.pdf
Burada vektörel kontrol konusunda çok fazla bilgi var. Anlatılmış aslında. Normalde olması gereken enkoderden gelen puls'lar sayılıp istenilen değere ulaştığında bir sonraki faz devreye alınıyor.


Ben şu dakika stm32'de bunu yapmaya kalksam kesmelerle felan yaparım. Acaba Frescalenin DSP'leri nasıl yapıyor bu işi?

Mucit23

Çözdüm gibi konuyu. En az iki adet Timer kullanmak gerekiyor. Timer'lerden bir tanesi encoder ile uğraşırken diğer Timer motor control işleriyle uğraşıyor. Timerler arasındaki iletişim Trigger ile gerçekleşiyor. Encoder ile uğraşan timerin değeri istenen değere ulaştığında triggerden diğer timere sinyal gönderiyor ve diğer timer bir sonraki komutayı veriyor. Kabaca böyle olması lazım.
Açıkçası bu konuyu çok merak ediyorum. Biraz araştırmam lazım çünkü çok kapsamlı bir konu.

magnetron

Mucit hocam

http://www22.brinkster.com/anotherbrick/index12.htm

ben de sizin gibi STM32F103 ile servo sürücü yapmaya çalıştım (resmi yukardaki linkte )

1 sene uğraştım herşey güzeldi motoru 2500 devire kadar çıkardım

ama motorun IPM sinin ( inteligent power module)  PWM kenarlarında enkoderde hatalı okumalar oluyordu
bu da motor dönerken tık tık ses gelip hatalı pozisyonlamasına neden oluyordu ( 3 - 5 puls kadar )
ne yaptıysam bu sorunu çözemedim

projeyi bıraktım

neden bu mesajı yazıyorum

siz enkoderi 2 timerla okutucam demişsiniz

ben tek timer da çözmüştüm - yani tek timerla oluyor
nasıl oluyor

timerin ilk 2 channel'iyle enkoderi okutuyorsunuz
kalan 2 channel ( channel 3 ve 4 ) compare şeklinde set ediyorsunuz
hem enkoder pozisyonunu okuyor hem de faz geçişlerinde CC3 ve CC4 interrupt oluşturup
burada IPM ye giden PWM lerin faz sırasını değiştiriyorsunuz
bunun için bir faz geçişleri tablosu oluşturuyorsunuz - yani enkoder 10000 e kadar sayıyor ya
24 tane de olabilecek faz geçişi var çünkü statorda 24 sargı var
işte 24 tane enkoder pozisyon sayısıyla interrupt içinde karşılaştırıp
faz sırasını değiştiriyorsunuz

yani demek istediğim tek timer la oluyor

kolay gelsin

bir de nacizane bir şey söyliyim
ben çiftyüzlü baskı devreyle yaptım - GND_plane yoktu
ama yukarda bahsettiğim problemle karşılaştım
yani böyle sorunlar çıkabiliyor - çok katlı PCB yapmanız gerekebilir

Mucit23

Hocam Tek Timer ile nasıl yaptınız anlayamadım. Normalde IPM Modülüne MCU'dan 6 Adet sinyal gider

PWM1H
PWM1L
PWM2H
PWM2L
PWM3H
PWM3L

Şuanda Tek bir Timerin ilk iki kanalı ile zaten enkoder okuması yapıyorum. Bunda sıkıntı yok. Geriye kalan 2 kanal (CH3-CH4)ile nasıl PWM sinyallerini üretiyorsunuz? ???
Olmaz
yani donanımsal olarak olmaz. Kesmeyle felan yapılır. Sizde mutlaka böyle birşey yapmışsınız.

Benim amacım oluyorsa eğer tüm işlemi donanımsal olarak yapmak. Ben sadece oturup çayımı içerken duty oranıyla oynayarak motorun devrini ayarlayacam. Tek hedefim budur.

Bu konuda da henüz anlayamadığım nokta şudur. Diyelim enkoderimiz  tur başına 1024 pals üretiyor ve motorumuzda 8 ayrı adımda 360 derecelik turunu tamamlıyor. Dolayısıyla 1024/8'den her 128 pals'de bir sonraki faz'a geçilmesi gerekir. Bu işlem nasıl yapılacak onu anlamış değilim. Birisi arka planda işlerin nasıl yürüdüğünü anlatsa çok iyi olurdu valla  ::)

Ben aslında bir dikiş makinası kartında STM32f103 ve Quadrature encoder kullanılarak Fırçasız dikiş makinası motoru süren bir kart görmüştüm. Keşke kodunu inceleme fırsatım olsaydı.

Elimde güçlü bir fırçasız motor var. Yani katalog bilgilerine göre 48'voltda 100A gibi bir akım çekebiliyor. Motorun orjinalinde encoder yok. Ben kendim bağlayacağım. Encoder olmadanda Motoru ESC ile çalıştırmıştım. Amacım bu motor için sürücü yapmak. Hazır sürücüler çok pahalı...

Sizin encoder probleminiz kafamı karıştırdı. STM32'nin donanımsal olarak böyle bir sorun yaratacağını sanmıyorum. Muhtemelen sizin encoderinizde problem vardı. Eğer çok yüksek pals'lı ise yüksek devirlerde artık encoder düzgün çalışmayabilir, puls kaçırabilir. Veya Encoder sinyallerini taşıyan hatlarda problem olabilir. Osiloskop ile bakmak lazım.


magnetron

Mucit hocam

PWM' i TIM8 ile ürettim

enkoderi TIM4 ile okudum ve TIM4' ün kalan iki channel ile
stator faz geçişlerinin enkoder değerlerinde CC3 ve CC4 interrupt oluşturdum

ordan TIM8'in COM interruptunu çağırdım
TIM_GenerateEvent(TIM8, TIM_EventSource_COM);

ve COM interrupt içinde fazları açıp kapadım

Mucit23

Şu STM32f103 ile 2x16 LCD çalıştırmak istiyorum.

LCD'yi 5V ile besledim.

Bağlantılarımı yazılımını felan hallettim fakat çalıştıramadım bir türlü. Hızdanmı kaynaklanıyor yoksa Data seviyesinin 3.3V olmasındanmı emin değilim.

Kullandığım LCD kütüphanesi budur.

/*----------------------------------------------------------------------------
 * Name:    LCD_4bit.c
 * Purpose: Functions for 2 line 16 character Text LCD (4-bit interface)
 *                connected on MCBSTM32 evaluation board 
 * Version: V1.10
 *----------------------------------------------------------------------------
 * This file is part of the uVision/ARM development tools.
 * This software may only be used under the terms of a valid, current,
 * end user licence from KEIL for a compatible version of KEIL software
 * development tools. Nothing else gives you the right to use this software.
 *
 * Copyright (c) 2005-2007 Keil Software. All rights reserved.
 *---------------------------------------------------------------------------*/

#include "STM32F10x.h"
#include "LCD_4bit.h"              /* STM32F10x Library Definitions      */

/*********************** Hardware specific configuration **********************/

/*------------------------- Speed dependant settings -------------------------*/

/* If processor works on high frequency delay has to be increased, it can be 
   increased by factor 2^N by this constant                                   */
#define DELAY_2N     0

/*------------------------- Text LCD size definitions ------------------------*/

#define LineLen     16                  /* Width (in characters)              */
#define NumLines     2                  /* Hight (in lines)                   */

/*-------------------- LCD interface hardware definitions --------------------*/

#define LCD_RS                GPIO_Pin_10
#define LCD_RW                GPIO_Pin_5
#define LCD_En                GPIO_Pin_11
#define LCD_D4                GPIO_Pin_12
#define LCD_D5                GPIO_Pin_13
#define LCD_D6                GPIO_Pin_14
#define LCD_D7                GPIO_Pin_15

/******************************************************************************/


/* 8 user defined characters to be loaded into CGRAM (used for bargraph)      */
const char UserFont[8][8] = {
  { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
  { 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10 },
  { 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18 },
  { 0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C },
  { 0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E },
  { 0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F },
  { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
  { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }
};

/************************ Global function definitions *************************/


/*******************************************************************************
* Delay in while loop cycles                                                   *
*   Parameter:    cnt:    number of while cycles to delay                      *
*   Return:                                                                    *
*******************************************************************************/

static void delay (int cnt)
{
  cnt <<= DELAY_2N;

  while (cnt--);
}

/*******************************************************************************
*   LCD Data Out                                                               *
*   Parameter:    c:      command to be written                                *
*   Return:                                                                    *
*******************************************************************************/
void lcd_data_out(unsigned char c)
{
  if((c & 0x01)==1){GPIO_SetBits(GPIOB,LCD_D4);}else{GPIO_ResetBits(GPIOB,LCD_D4);}
  if((c & 0x02)>>1==1){GPIO_SetBits(GPIOB,LCD_D5);}else{GPIO_ResetBits(GPIOB,LCD_D5);}
  if((c & 0x04)>>2==1){GPIO_SetBits(GPIOB,LCD_D6);}else{GPIO_ResetBits(GPIOB,LCD_D6);}
  if((c & 0x08)>>3==1){GPIO_SetBits(GPIOB,LCD_D7);}else{GPIO_ResetBits(GPIOB,LCD_D7);}
}

/*******************************************************************************
*   LCD Data in                                                                *
*   Parameter:                                                                 *
*   Return: lcd_data                                                           *
*******************************************************************************/
unsigned char lcd_data_in(void)
{
   unsigned char temp=0;
	
	 temp |= ((unsigned char)3<<GPIO_ReadInputDataBit(GPIOB,LCD_D7));
	 temp |= ((unsigned char)2<<GPIO_ReadInputDataBit(GPIOB,LCD_D6));
	 temp |= ((unsigned char)1<<GPIO_ReadInputDataBit(GPIOB,LCD_D5));
	 temp |= (unsigned char)GPIO_ReadInputDataBit(GPIOB,LCD_D4);
	
	return temp;
}

void lcd_dir_in(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin = LCD_D4 | LCD_D5 | LCD_D6 | LCD_D7;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
}

void lcd_dir_out(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin = LCD_D4 | LCD_D5 | LCD_D6 | LCD_D7;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
}

/*******************************************************************************
* Read status of LCD controller                                                *
*   Parameter:    none                                                         *
*   Return:       Status byte contains busy flag and address pointer           *
*******************************************************************************/
static unsigned char lcd_read_status (void)
{
  unsigned char status;

  GPIO_ResetBits(GPIOB,LCD_RS);
  GPIO_SetBits(GPIOB,LCD_RW);
  delay(10);
  GPIO_SetBits(GPIOB,LCD_En);
  delay(10);
  status  = (unsigned char)lcd_data_in() << 4;
  GPIO_ResetBits(GPIOB,LCD_En);
  delay(10);
  GPIO_SetBits(GPIOB,LCD_En);
  delay(10);
  status |= lcd_data_in();
  GPIO_ResetBits(GPIOB,LCD_En);
  lcd_dir_out();
  return (status);
}


/*******************************************************************************
* Wait until LCD controller busy flag is 0                                     *
*   Parameter:                                                                 *
*   Return:       Status byte of LCD controller (busy + address)               *
*******************************************************************************/

static unsigned char wait_while_busy (void)
{
  unsigned char status;

  do{
    status = lcd_read_status();
  }
	while (status & 0x80);             /* Wait for busy flag                 */

  return (status);
}


/*******************************************************************************
* Write 4-bits to LCD controller                                               *
*   Parameter:    c:      command to be written                                *
*   Return:                                                                    *
*******************************************************************************/

void lcd_write_4bit (unsigned char c)
{
	GPIO_ResetBits(GPIOB,LCD_RW);
  GPIO_SetBits(GPIOB,LCD_En);
  lcd_data_out(c);
  delay(10);
  GPIO_ResetBits(GPIOB,LCD_En);
  delay(10);
}


/*******************************************************************************
* Write command to LCD controller                                              *
*   Parameter:    c:      command to be written                                *
*   Return:                                                                    *
*******************************************************************************/

void lcd_write_cmd (unsigned char c)
{
  wait_while_busy();

  GPIO_ResetBits(GPIOB,LCD_RS);
  lcd_write_4bit (c>>4);
  lcd_write_4bit (c);
}


/*******************************************************************************
* Write data to LCD controller                                                 *
*   Parameter:    c:      data to be written                                   *
*   Return:                                                                    *
*******************************************************************************/

static void lcd_write_data (unsigned char c)
{
  wait_while_busy();

  GPIO_SetBits(GPIOB,LCD_RS);
  lcd_write_4bit (c>>4);
  lcd_write_4bit (c);
}


/*******************************************************************************
* Print Character to current cursor position                                   *
*   Parameter:    c:      character to be printed                              *
*   Return:                                                                    *
*******************************************************************************/

void lcd_putchar (char c)
{ 
  lcd_write_data (c);
}


/*******************************************************************************
* Initialize the LCD controller                                                *
*   Parameter:                                                                 *
*   Return:                                                                    *
*******************************************************************************/

void lcd_init (void)
{ 
  int i;
  char const *p;
	
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE);
	
	GPIO_InitStructure.GPIO_Pin =  LCD_RS | LCD_RW | LCD_En |LCD_D4 | LCD_D5 | LCD_D6 | LCD_D7;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);

  /* Set all pins for LCD as outputs                                          */
  lcd_dir_out();

  delay (15000);
  GPIO_ResetBits(GPIOB,LCD_RS);
  lcd_write_4bit (0x03);                 /* Select 4-bit interface             */
  delay (4100);
  lcd_write_4bit (0x03);
  delay (100);
  lcd_write_4bit (0x03);
  lcd_write_4bit (0x02);

  lcd_write_cmd (0x28);                 /* 2 lines, 5x8 character matrix      */
  lcd_write_cmd (0x0C);                 /* Display ctrl:Disp=ON,Curs/Blnk=OFF */
  lcd_write_cmd (0x06);                 /* Entry mode: Move right, no shift   */

  /* Load user-specific characters into CGRAM                                 */
  lcd_write_cmd(0x40);                  /* Set CGRAM address counter to 0     */
  p = &UserFont[0][0];
  for (i = 0; i < sizeof(UserFont); i++, p++)
    lcd_putchar (*p);

  lcd_write_cmd(0x80);                  /* Set DDRAM address counter to 0     */
}



/*******************************************************************************
* Set cursor position on LCD display                                           *
*   Parameter:    column: column position                                      *
*                 line:   line position                                        *
*   Return:                                                                    *
*******************************************************************************/

void set_cursor (int column, int line)
{
  unsigned char address;

  address = (line * 40) + column;
  address = 0x80 + (address & 0x7F);
  lcd_write_cmd(address);               /* Set DDRAM address counter to 0     */
}

/*******************************************************************************
* Clear the LCD display                                                        *
*   Parameter:                                                                 *
*   Return:                                                                    *
*******************************************************************************/

void lcd_clear (void)
{
  lcd_write_cmd(0x01);                  /* Display clear                      */
  set_cursor (0, 0);
}


/*******************************************************************************
* Print sting to LCD display                                                   *
*   Parameter:    string: pointer to output string                             *
*   Return:                                                                    *
*******************************************************************************/

void lcd_print (char *string)
{
  while (*string)  {
    lcd_putchar (*string++);
  }
}


/*******************************************************************************
* Print a bargraph to LCD display                                              *
*   Parameter:     val:  value 0..100 %                                        *
*                  size: size of bargraph 1..16                                *
*   Return:                                                                    *
*******************************************************************************/
void lcd_bargraph (int value, int size) {
   int i;

   value = value * size / 20;            /* Display matrix 5 x 8 pixels       */
   for (i = 0; i < size; i++) {
      if (value > 5) {
         lcd_putchar (0x05);
         value -= 5;
      }
      else {
         lcd_putchar (value);
         break;
      }
   }
}


/*******************************************************************************
* Display bargraph on LCD display                                              *
*   Parameter:     pos_x: horizontal position of bargraph start                *
*                  pos_y: vertical position of bargraph                        *
*                  value: size of bargraph active field (in pixels)            *
*   Return:                                                                    *
*******************************************************************************/

void lcd_bargraphXY (int pos_x, int pos_y, int value) {
  int i;

  set_cursor (pos_x, pos_y);
  for (i = 0; i < 16; i++)  {
    if (value > 5) {
      lcd_putchar (0x05);
      value -= 5;
    } else {
      lcd_putchar (value);
      while (i++ < 16) lcd_putchar (0);
    }
  }
}

/******************************************************************************/


Kütüphaneyi keilin kendi örnekleri içerisinden aldım sonradan giriş çıkışlar üzerinde biraz oynadım. Data gönderme ve alma rutinlerini STD library fonksiyonları ile yaptım. Epeyce bi inceledim problem göremedim ama emin değilim. Neden olabilir? Kütüphaneyi inceleyebilirmisiniz?

Mucit23

STM32F10X in CAN Controller modülü hakkında sormak istediğim birkaç soru var.

Elimde CanBus ile ilgili deney kartlarıyla gelen ve internetten topladığım birkaç örnek program var. Bu örnek programlara bakarak kendime göre temiz bir Can kütüphanesi oluşturmaya çalışıyorum.

Can RX interruptunu kullanmak istiyorum. Bir yerden mesaj geldiği zaman kesme oluşsun. stm32f10x_it.c içerisinde gelen mesajlarla ilgili iki adet kesme vektörü gördüm biraz kafam karıştı.

/*******************************************************************************
* Function Name  : USB_LP_CAN_RX0_IRQHandler
* Description    : This function handles USB Low Priority or CAN RX0 interrupts 
*                  requests.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void USB_LP_CAN_RX0_IRQHandler(void)
{
}

/*******************************************************************************
* Function Name  : CAN_RX1_IRQHandler
* Description    : This function handles CAN RX1 interrupt request.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void CAN_RX1_IRQHandler(void)
{
}


Bu ikisi arasındaki fark nedir? Birde Neden USB ile Can interruptları tek bir kesme vektörüne aktarılmış?

Ben Can interruptunu kurarken aşağıdaki gibi bir kurulum yapıyorum.

  CAN_ITConfig(CAN1,CAN_IT_FMP0, ENABLE);   //Enable FIFO 0 message pending interrupt*/

Yukarıdaki gibi bir kurulumla kesme hangi kesme vektörüne düşer?

Teşekkürler


Erol YILMAZ

STM32F103 te USB ve CAN aynı anda kullanılamıyor diye aklımda kalmış.

Mucit23

Evet USB ve Can Meselesi öyleymiş.

RM0008 Sayfa:629

Note: In low, medium-, high- and XL-density devices the USB and CAN share a dedicated 512-
byte SRAM memory for data transmission and reception, and so they cannot be used
concurrently (the shared SRAM is accessed through CAN and USB exclusively). The USB
and CAN can be used in the same application but not at the same time.


Sanırım USB ile CAN'ın tek interruptlarının tek vektörde birleştirilmesinin sebebi budur.

Ben birde STM32'nin Can Modülündeki Filtre olayını anlayamadım. Anladığım kadarıyla Sadece belirtilen idlerden gelen mesajları alması sağlanıyor fakat nasıl kurulduğunu anlayamadım.

Örneğin benim id'im 0x123 olsun. Can modülü sadece bu id'den gelen mesajlar için kesme oluştursun. Filtreyi nasıl ayarlamam gerekiyor?

  /* CAN filter init */
  CAN_FilterInitStructure.CAN_FilterNumber=0;
  CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
  CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;
  CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;
  CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
  CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;
  CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
  CAN_FilterInitStructure.CAN_FilterFIFOAssignment=0;
  CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
  CAN_FilterInit(&CAN_FilterInitStructure);


Erol YILMAZ

Maske ve Filtre konusu sadece STM32 CAN'e ait değil.
Genel olarak netten bulduğum örneklem :

Example 1. we wish to accept only frames with ID of 00001567 (hexadecimal values)
set filter to 00001567
set mask to 1FFFFFFF

when a frame arrives its ID is compared with the filter and all bits must match; any frame that does not match ID 00001567 is rejected

Example 2. we wish to accept only frames with IDs of 00001560 thru to 0000156F
set filter to 00001560
set mask to 1FFFFFF0

when a frame arrives its ID is compared with the filter and all bits except bits 0 to 3 must match; any frame other frame is rejected


Example 3. we wish to accept only frames with IDs of 00001560 thru to 00001567
set filter to 00001560
set mask to 1FFFFFF8

when a frame arrives its ID is compared with the filter and all bits except bits 0 to 2 must match; any frame other frame is rejected

Example 4. we wish to accept any frame
set filter to 0
set mask to 0

all frames are accepted

Mucit23

Anladığım kadarıyla maske ve filtre 0 verilince bütün gelen mesajlar kabul ediliyor. Ben şimdilik çalışmalarımı böyle yapacam ama anlamadığım şey şu maske konusu. Tamam kabul edilecek adres filtre kısmına yazılıyor. peki maske ne işe yarıyor onu bir türlü anlayamadım.

CLR

Bu konuyu biraz açıklayayım, gerisini sen getir.

Stm32 can interface konusunda oldukça flexible bir işlemcidir, muhteşem filtre özellikleri var mesela 4 tane filtreleme çeşiti var.
1) 32bit Idmask
2) 32bit idlist
3) 16bit idmask
4) 16bit idlist 

32 bit olanlar extended id(29bit) ve standart id(11bit) ile haberleşilirken kullanılıyor
16bit olanlar ise(16bite kadar extended) veya 11bit std id olarak kullanılabilir.

Filtre ve mask kısmına gelince
Filtre ile maske bit bit karşılaştırılır
maske biti 0 ise fitrede ne varsa geçer yani don't care durumu
maske biti 1 ise filtre biti ile gelen mesajdaki ilgili bit aynı olmak zorundadır, aynı değilse stm32 filtre donanımı bu mesajı reddeder.

Mesaj geçerse filtre için tanımladığın can fifoya mesaj yerleştirilir ve fifonun flag'i set olur. İnterrupt kurduysan ki mutlaka kur, int içinde mesajı oku

Bir örnek vereyim

Can bustan sadece ID'si 0x12345678 olan mesajı almak istiyorsam

Filtre Registeri içeriği : 0x12345678
Mask register            : 0xFFFFFFFFF

can bustan  ID'leri 0x12345670,0x12345671,0x12345672......0x1234567F olan mesajı almak istiyorsam yani 16 farklı id

Filtre Registeri içeriği : 0x12345670
Mask register            : 0xFFFFFFFF0

Daha çok çeşitli varyasyon ve durum var ama bu kadarı senin işini çözecektir,

Filtre ve mask 0 yaparsan donanım herşeyi içeri alır, multislave olan yerlerde işlemci mesajlara yetişemez zaten filtrenin var olma amacı budur, gereksiz mesajlarla uğraşmasın diye   


Olay bundan ibaret     
Knowledge and Experience are Power

Mucit23

#297
Tamamdır hocam çaktım meseleyi. Bu açıklama iyi oldu. Teşekkürler.

mesaj birleştirme:: 11 Ağustos 2014, 23:43:37

@CLR Hocam Can ile ilgili ilk testimi yaptım fakat haberleşmeyi sağlayamadım.

Bir tarafta STM32 ve SN65HVD230 ikilisi karşı tarafta ise MCP2515 ve 2551 ikilisi var. MCP2515'i kontrol etmek içinde pic var 100ms aralıklarla MCP2515'e mesaj gönderiyor. Burada CCS'nin standart MCP2515 kütüphanesini kullandım.

STM32 ilede sürekli veri basıyorum fakat CAN_TX de herhangi bir hareketlenme görmüyorum. . Henüz neden kaynaklandığını çözemedim. 

Ama şunu gözlemledim. MCP2515 Transmit görevini yapıyor gibi. Osiloskop ile STM32'nin CAN RX ucuna baktığımda sürekli birşeyler geldiğini görebiliyorum. Demekki MCP birleyler gönderiyor. Fakat STM32'nin CAN TX inde birşey yok.

STM32'de Can için kullandığım kütüphane budur.

/*******************************************************************************
* @file    can.c
* @author  Arectron
* @version V1.0.0
* @date    10/08/2014     
********************************************************************************/
/*-------------------------------Includes------------------------------------*/
 #include "STM32F10x.h"
 #include "CAN.h"
/* Private variables ---------------------------------------------------------*/
  CanRxMsg RxMessage;
	uint8_t CanFlag=0;
/* Private Functions ---------------------------------------------------------*/

/*******************************************************************************
* Function Name  : NVIC_Configuration
* Description    : Configures the nested vectored interrupt controller.
* Input          : None
* Output         : None
* Return         : None
* Attention		 : None
*******************************************************************************/
void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;

  /* Enable CAN1 RX0 interrupt IRQ channel */
  NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}

/*******************************************************************************
* Function Name  : GPIO_Configuration
* Description    : Configures the CAN GPIO ports.
* Input          : None
* Output         : None
* Return         : None
* Attention		 : None
*******************************************************************************/
void GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  /* CAN Periph clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO ,ENABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
   
  /* Configure CAN pin: RX */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOB, &GPIO_InitStructure);   
  /* Configure CAN pin: TX */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOB, &GPIO_InitStructure);	   
	
	GPIO_PinRemapConfig(GPIO_Remap1_CAN1,ENABLE);
 
}

/*******************************************************************************
* Function Name  : CAN_init
* Description    : Configures the CAN
* Input          : None
* Output         : None
* Return         : None
* Attention		 : None
*******************************************************************************/
void Can_init(void)
{
  CAN_InitTypeDef CAN_InitStructure;
  CAN_FilterInitTypeDef CAN_FilterInitStructure;

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);	
	
  NVIC_Configuration();
  GPIO_Configuration();
	
  CAN_DeInit(CAN1);
  CAN_StructInit(&CAN_InitStructure);
	
  /* CAN cell init */
  CAN_InitStructure.CAN_TTCM=DISABLE;
  CAN_InitStructure.CAN_ABOM=DISABLE;
  CAN_InitStructure.CAN_AWUM=DISABLE;
  CAN_InitStructure.CAN_NART=DISABLE;
  CAN_InitStructure.CAN_RFLM=DISABLE;
  CAN_InitStructure.CAN_TXFP=DISABLE;
  CAN_InitStructure.CAN_Mode=CAN_Mode_Normal;
  CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;
  CAN_InitStructure.CAN_BS1=CAN_BS1_8tq;
  CAN_InitStructure.CAN_BS2=CAN_BS2_7tq;
  CAN_InitStructure.CAN_Prescaler=5;
  CAN_Init(CAN1,&CAN_InitStructure);  

  /* CAN filter init */
  CAN_FilterInitStructure.CAN_FilterNumber=0;
  CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
  CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;
  CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;
  CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
  CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;
  CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
  CAN_FilterInitStructure.CAN_FilterFIFOAssignment=0;
  CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
  CAN_FilterInit(&CAN_FilterInitStructure);
	
  CAN_ITConfig(CAN1,CAN_IT_FMP0, ENABLE);
}

/*******************************************************************************
* Function Name  : CanSendMessage
* Description    : Can Write Date to CAN-BUS
* Input          : None
* Output         : None
* Return         : None
* Attention		 : None
*******************************************************************************/
void CanSendMessage(uint32_t CanTxId, uint8_t CanTxBufSize, uint8_t* CanTxData)
{
  CanTxMsg TxMessage;
  uint8_t i=0;
  /* transmit */
  TxMessage.StdId = CanTxId;   
  TxMessage.RTR = CAN_RTR_DATA;
  TxMessage.IDE = CAN_ID_STD;  
  TxMessage.DLC = CanTxBufSize;            
   
  for(i=0;i<CanTxBufSize;i++)
	{
     TxMessage.Data[i]=CanTxData[i];
  }
	
  CAN_Transmit(CAN1,&TxMessage); 	
}


/*******************************************************************************
* Function Name  : USB_LP_CAN1_RX0_IRQHandler
* Description    : This function handles USB Low Priority or CAN RX0 interrupts 
* Input          : None
* Output         : None
* Return         : None
* Attention		   : None
*******************************************************************************/
void USB_LP_CAN_RX0_IRQHandler(void)
{
  CAN_Receive(CAN1,CAN_FIFO0, &RxMessage);  
  CAN_ClearITPendingBit(CAN1,CAN_IT_FMP0);  
  CanFlag=ENABLE;
}


Sağdan soldan toparladığım kodları düzenleyerek oluşturdum. Ben bir tek CanSendMessage Fonksiyonunu yazdım. Ana programda bu fonksiyonu çağırıyorum. Örneğin aşağıdaki gibi.

CanSendMessage(0x202,1,&buff[0]);


Program bu fonksiyona gidip geliyor  fakat CAN_TX de hiçbir hareketlenme olmuyor. Neden kaynaklanıyor bilmiyorum. CAN ile ilk kez uğraşıyorum. konu hakkında fazla tecrübem yok. Kodları bi inceleyip varsa eksiklerim söylerseniz memnun olurum.

Birde Şu CAN_Baudrate konusunda biraz bilgi verirseniz sevinirim. Baudrate ayarını yapmak için CCS de fonksiyon var fakat STM32'de bu konuda pek birşey bulamadım. İlgili olabilecek Birtek CAN_Prescaller var onuda nasıl ayarlayacağım bilmiyorum.

Yardım ederseniz çok memnun olurum.

mesaj birleştirme:: 12 Ağustos 2014, 00:43:47

@CLR Hocam Can ile ilgili ilk testimi yaptım fakat haberleşmeyi sağlayamadım.

Bir tarafta STM32 ve SN65HVD230 ikilisi karşı tarafta ise MCP2515 ve 2551 ikilisi var. MCP2515'i kontrol etmek içinde pic var 100ms aralıklarla MCP2515'e mesaj gönderiyor. Burada CCS'nin standart MCP2515 kütüphanesini kullandım.

STM32 ilede sürekli veri basıyorum fakat CAN_TX de herhangi bir hareketlenme görmüyorum. . Henüz neden kaynaklandığını çözemedim. 

Ama şunu gözlemledim. MCP2515 Transmit görevini yapıyor gibi. Osiloskop ile STM32'nin CAN RX ucuna baktığımda sürekli birşeyler geldiğini görebiliyorum. Demekki MCP birleyler gönderiyor. Fakat STM32'nin CAN TX inde birşey yok.

STM32'de Can için kullandığım kütüphane budur.

/*******************************************************************************
* @file    can.c
* @author  Arectron
* @version V1.0.0
* @date    10/08/2014     
********************************************************************************/
/*-------------------------------Includes------------------------------------*/
 #include "STM32F10x.h"
 #include "CAN.h"
/* Private variables ---------------------------------------------------------*/
  CanRxMsg RxMessage;
	uint8_t CanFlag=0;
/* Private Functions ---------------------------------------------------------*/

/*******************************************************************************
* Function Name  : NVIC_Configuration
* Description    : Configures the nested vectored interrupt controller.
* Input          : None
* Output         : None
* Return         : None
* Attention		 : None
*******************************************************************************/
void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;

  /* Enable CAN1 RX0 interrupt IRQ channel */
  NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}

/*******************************************************************************
* Function Name  : GPIO_Configuration
* Description    : Configures the CAN GPIO ports.
* Input          : None
* Output         : None
* Return         : None
* Attention		 : None
*******************************************************************************/
void GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  /* CAN Periph clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO ,ENABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
   
  /* Configure CAN pin: RX */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOB, &GPIO_InitStructure);   
  /* Configure CAN pin: TX */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOB, &GPIO_InitStructure);	   
	
	GPIO_PinRemapConfig(GPIO_Remap1_CAN1,ENABLE);
 
}

/*******************************************************************************
* Function Name  : CAN_init
* Description    : Configures the CAN
* Input          : None
* Output         : None
* Return         : None
* Attention		 : None
*******************************************************************************/
void Can_init(void)
{
  CAN_InitTypeDef CAN_InitStructure;
  CAN_FilterInitTypeDef CAN_FilterInitStructure;

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);	
	
  NVIC_Configuration();
  GPIO_Configuration();
	
  CAN_DeInit(CAN1);
  CAN_StructInit(&CAN_InitStructure);
	
  /* CAN cell init */
  CAN_InitStructure.CAN_TTCM=DISABLE;
  CAN_InitStructure.CAN_ABOM=DISABLE;
  CAN_InitStructure.CAN_AWUM=DISABLE;
  CAN_InitStructure.CAN_NART=DISABLE;
  CAN_InitStructure.CAN_RFLM=DISABLE;
  CAN_InitStructure.CAN_TXFP=DISABLE;
  CAN_InitStructure.CAN_Mode=CAN_Mode_Normal;
  CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;
  CAN_InitStructure.CAN_BS1=CAN_BS1_8tq;
  CAN_InitStructure.CAN_BS2=CAN_BS2_7tq;
  CAN_InitStructure.CAN_Prescaler=5;
  CAN_Init(CAN1,&CAN_InitStructure);  

  /* CAN filter init */
  CAN_FilterInitStructure.CAN_FilterNumber=0;
  CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
  CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;
  CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;
  CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
  CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;
  CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
  CAN_FilterInitStructure.CAN_FilterFIFOAssignment=0;
  CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
  CAN_FilterInit(&CAN_FilterInitStructure);
	
  CAN_ITConfig(CAN1,CAN_IT_FMP0, ENABLE);
}

/*******************************************************************************
* Function Name  : CanSendMessage
* Description    : Can Write Date to CAN-BUS
* Input          : None
* Output         : None
* Return         : None
* Attention		 : None
*******************************************************************************/
void CanSendMessage(uint32_t CanTxId, uint8_t CanTxBufSize, uint8_t* CanTxData)
{
  CanTxMsg TxMessage;
  uint8_t i=0;
  /* transmit */
  TxMessage.StdId = CanTxId;   
  TxMessage.RTR = CAN_RTR_DATA;
  TxMessage.IDE = CAN_ID_STD;  
  TxMessage.DLC = CanTxBufSize;            
   
  for(i=0;i<CanTxBufSize;i++)
	{
     TxMessage.Data[i]=CanTxData[i];
  }
	
  CAN_Transmit(CAN1,&TxMessage); 	
}


/*******************************************************************************
* Function Name  : USB_LP_CAN1_RX0_IRQHandler
* Description    : This function handles USB Low Priority or CAN RX0 interrupts 
* Input          : None
* Output         : None
* Return         : None
* Attention		   : None
*******************************************************************************/
void USB_LP_CAN_RX0_IRQHandler(void)
{
  CAN_Receive(CAN1,CAN_FIFO0, &RxMessage);  
  CAN_ClearITPendingBit(CAN1,CAN_IT_FMP0);  
  CanFlag=ENABLE;
}


Sağdan soldan toparladığım kodları düzenleyerek oluşturdum. Ben bir tek CanSendMessage Fonksiyonunu yazdım. Ana programda bu fonksiyonu çağırıyorum. Örneğin aşağıdaki gibi.

CanSendMessage(0x202,1,&buff[0]);


Program bu fonksiyona gidip geliyor  fakat CAN_TX de hiçbir hareketlenme olmuyor. Neden kaynaklanıyor bilmiyorum. CAN ile ilk kez uğraşıyorum. konu hakkında fazla tecrübem yok. Kodları bi inceleyip varsa eksiklerim söylerseniz memnun olurum.

Birde Şu CAN_Baudrate konusunda biraz bilgi verirseniz sevinirim. Baudrate ayarını yapmak için CCS de fonksiyon var fakat STM32'de bu konuda pek birşey bulamadım. İlgili olabilecek Birtek CAN_Prescaller var onuda nasıl ayarlayacağım bilmiyorum.

Yardım ederseniz sevinirim.

CLR

Kaç kbit'te haberleşmek istiyorsun veya MCP2515 Kaç kbitte gönderiyor? İşlemci çalışma frekansı?

Scop ile can tx pinine baktın mı?
Knowledge and Experience are Power

Mucit23

Hocam Usart cinsinden söylemek gerekirse 9600 Baudrate gibi bir değer işimi görür.

STM32F103 zaten 72Mhz de çalışıyor. MCP2515 ise şuanda Baudrate Prescalleri 4 olarak ayarlı. Ayrıca MCP2515'e 16Mhz Harici Osilatör bağlı. Çalışma frekansları farklı olduğundan iki çipinde baudrate prescalleri aynı yapılmaz herhalde. Yani ben öyle tahmin ediyorum. @CLR hocam tam olarak ne yapmam gerekiyor?

STM32'de CAN_TX pinine osiloskop ile bakıyorum hiçbirşey yok. Sürekli lojik1 konumunda.

Şunu anlamıyorum. Baudrate yanlış bile olsa STM32'den veri çıkması lazım. Fakat STM32'nin CAN modülü sankide hiç çalışmıyor. Anlam veremedim.
Fikri olan varmı?