www.elektronik.si Seznam forumov www.elektronik.si
Forum o elektrotehniki in računalništvu
 
 PomočPomoč  IščiIšči  Seznam članovSeznam članov  SkupineSkupine  StatisticsStatistika  AlbumAlbum  DatotekeFilemanager DokumentacijaDocDB LinksPovezave   Registriraj seRegistriraj se 
  PravilaPravila  LinksBolha  PriponkePriponke  KoledarKoledar  ZapiskiZapiski Tvoj profilTvoj profil Prijava za pregled zasebnih sporočilPrijava za pregled zasebnih sporočil PrijavaPrijava 

STM32 in SPI komunikacija

 
Objavi novo temo   Odgovori na to temo   Printer-friendly version    www.elektronik.si Seznam forumov -> ARM arhitektura
Poglej prejšnjo temo :: Poglej naslednjo temo  
Avtor Sporočilo
urosg
Član
Član



Pridružen-a: Pet 27 Apr 2007 14:30
Prispevkov: 565
Aktiv.: 2.56

PrispevekObjavljeno: Tor Avg 09, 2011 8:43 am    Naslov sporočila: icon_question STM32 in SPI komunikacija Odgovori s citatom

Spravil sem se na SPI komunikacijo med STM32F103C8 in temperaturnim modulom DC-SS500 (SureElectronics).

Komunikacija med enotama preko UART in preko ADCja mi deluje, vendar ker mi UART ni všeč zaradi dodatnega "dekodiranja" prebranih tekstov, z ADC je pa problem ker za temperaturo ni linearen izhod od modula in ni podatka kako točno izračunat temperaturo iz prejete vrednosti ampak so samo referenčne vrednosti pri določenih vhodnih voltažah.

No zaradi tega sem želel narediti še povezavo preko SPI, kjer se lepo pošlje in prejme po en bajt za željeno vrednost.

Težava je v tem, da ko pošljem podatek modulu, se RXNE bit na SPIju postavi na TRUE, vendar se v naslednjem ciklu zresetira še predno ga lahko sploh preberem.

Za clock uporabljam interni oscilator STMa, brez PLLja; SPI uporabljam brez interuptov preverjam z GetFlagStatus stanje.

Čudno mi je, da se RXNE po tem, ko jaz pošljem podatek na modul postavi in tudi v data registru SPIja vidim vrednost vendar se RXNE takoj ko dam "Step" zresetira tako da ga GetFlagStatus ne dobi.

Ima kdo kakšno idejo kje bi lahko bil problem? Malo sicer sumim, da je interni oscilator preveč nestabilen, čeprav mi output UARTa deluje zelo lepo.

LP, Uroš
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo
aly
Član
Član



Pridružen-a: Tor 28 Sep 2004 14:51
Prispevkov: 9407
Aktiv.: 39.75
Kraj: Kranj - struževo

PrispevekObjavljeno: Tor Avg 09, 2011 9:55 am    Naslov sporočila:   Odgovori s citatom

Tale RXNE zastavica je tudi mene nekaj hecala. Ampak samo takrat, ko sem pošiljal oz. prejemal večjo količino podatkov hkrati v 8-bitnem načinu.
Če sem pošiljal in sprejemal samo po en word (16 bitov) naenkrat, je delalo.

Potem pa te komunikacije nisem več rabil in se nisem več s tem ukvarjal.

Za test poskusi gledati TX empty zastavico in ko se aktivira, počakaj en čas (da bo oddaja in sprejem dokončan) in potem "na slepo" preberi RX register.

Stabilnost oscilatorja pri SPI nima veze.

_________________
I'm going to stand outside, so if anyone asks, I'm outstanding Smile
Nazaj na vrh
Skrit Poglej uporabnikov profil Pošlji zasebno sporočilo Obišči avtorjevo spletno stran MSN Messenger - naslov
urosg
Član
Član



Pridružen-a: Pet 27 Apr 2007 14:30
Prispevkov: 565
Aktiv.: 2.56

PrispevekObjavljeno: Tor Avg 09, 2011 7:23 pm    Naslov sporočila:   Odgovori s citatom

Aly hvala za odgovor, sem poiskusil tudi tvoj nacin, pa nekako ne gre.

Po malo brskanja po internetu sem nasel primer povezave takega modula z arduinom in sem prenesel nastavitve iz tistega primera v mojo kodo - nastavitve za CPOL, CPHA, ... pa se vedno nimam zadovoljivih rezultatov.

Problem je ker najprej zelim prebrati "IDLE" status modula, zatem prebrati temperaturo in potem RV.

Glede na to da so rezultati cisto nakljucni ne vem kje bi naprej iskal napako, namrec naredil sem si zanko, ki:
- postavi /CS na LOW
1. zresetira RXNE bit
2. preveri TXE bit
3. poslje komando za status
4. caka na RXNE bit
5. malo pocaka
6. prebere prejeti podatek
- postavi /CS na HIGH

pricakovan odgovor je zelo redko pravilen.

Ne vem kje bi se iskal napako oz. mozen vzrok temu.

koda:
Koda:

#include <stm32f10x_lib.h>
#include <stm32f10x_rcc.h>
#include <stm32f10x_gpio.h>
#include <stm32f10x_usart.h>
#include <stm32f10x_spi.h>
#include <stdio.h>
#include <math.h>

/* function prototypes */
void RCC_Configuration(void);
void GPIO_Configuration(void);
void Delay(vu32 nCount);
unsigned int GetADC1Channel(unsigned char chanel, int reads);

/* set up clock sources */
void RCC_Configuration(void)
{
  /* enable peripherals */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO | RCC_APB2Periph_USART1 | RCC_APB2Periph_ADC1 | RCC_APB2Periph_SPI1, ENABLE);
}       
       
/* configure I/O ports */
void GPIO_Configuration(void)
{
/*
  LED STRIP (1..10)
  PB5  = 41
  PB6  = 42
  PB7  = 43
  PB8  = 45
  PB9  = 46
  PB10 = 21
  PB11 = 22
  PB12 = 25
  PB13 = 26
  PB14 = 27
 
  PIR Sensor
  PA15 = 38

  UART1
  PA9  = TX
  PA10 = RX
*/
  /* pin configuration parameters */
  GPIO_InitTypeDef GPIO_InitStructure;
  USART_InitTypeDef USART_InitStructure;
  SPI_InitTypeDef SPI_InitStructure;
 
  /* configure PC7 as output push-pull  */
  GPIO_StructInit(&GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOB, &GPIO_InitStructure);

  GPIO_StructInit(&GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  GPIO_StructInit(&GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* Configure ADC pins */
  GPIO_StructInit(&GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* Configure USART1_Tx as 'alternate function push-pull' */
  GPIO_StructInit(&GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  /* Configure USART1_Rx as 'input floating' */
  GPIO_StructInit(&GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* Configure SPI ports */
  /*  Configure output pins */
  GPIO_StructInit(&GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; // SSEL
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  GPIO_StructInit(&GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; // SCK, MISO, MOSI
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* USART parameters */
  USART_StructInit(&USART_InitStructure);
  USART_InitStructure.USART_BaudRate = 9600;
  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;
  /* Configuring and enabling USART1 */
  USART_Init(USART1, &USART_InitStructure);
  USART_Cmd(USART1, ENABLE);

  /* SPI parameters */
  SPI_I2S_DeInit(SPI1);
  SPI_StructInit(&SPI_InitStructure);
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  SPI_InitStructure.SPI_CRCPolynomial = 7;
  SPI_Init(SPI1, &SPI_InitStructure);
  SPI_CalculateCRC(SPI1, DISABLE);
  SPI_Cmd(SPI1, ENABLE);

  // reset leds
  GPIO_SetBits(GPIOB, GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14);
  GPIO_SetBits(GPIOA, GPIO_Pin_0);
  GPIO_SetBits(GPIOA, GPIO_Pin_4); // pull high to disable SPI
}

/* wait */
void Delay(vu32 nCount)
{
  while (nCount--);
}

/***************************************************************************************************************************/
void InitADC1(void) {
  ADC_InitTypeDef   ADC_InitStructure;

  // ADC init
  // ADC Deinit
  ADC_DeInit(ADC1);

  // ADC Structure Initialization
  ADC_StructInit(&ADC_InitStructure);

  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;
  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfChannel = 1;
  ADC_Init(ADC1, &ADC_InitStructure);

  // Enable the ADC
  ADC_Cmd(ADC1, ENABLE);

  // ADC calibration
  // Enable ADC1 reset calibaration register
  ADC_ResetCalibration(ADC1);
 
  // Check the end of ADC1 reset calibration register
  while(ADC_GetResetCalibrationStatus(ADC1) == SET);

  // Start ADC1 calibaration
  ADC_StartCalibration(ADC1);
 
  // Check the end of ADC1 calibration
  while(ADC_GetCalibrationStatus(ADC1) == SET);
}

unsigned int GetADC1Channel(unsigned char chanel, int reads)
{
  unsigned int retVal = 0;
  int i;
  // Configure channel
  ADC_RegularChannelConfig(ADC1, chanel, 1, ADC_SampleTime_55Cycles5);

  for (i = 0; i < reads; i++) {
    // Start the conversion
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);
    // Wait until conversion completion
    while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
    // Get the conversion value
   retVal = retVal + ADC_GetConversionValue(ADC1);
  }
  return retVal / reads;
}
/************************************************************************************************************/

/* Write the 'ch' character into the 'f' file */
int fputc(int ch, FILE * f) {
  USART_SendData(USART1, (u8) ch);
  while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
  return ch;
}

u8 readSPI(u8 data) {
   u8 spiData = 0xFF;
//   int i;
   GPIO_ResetBits(GPIOA, GPIO_Pin_4); // pull low to enable SPI
   Delay(0xA7FFFF);
   SPI_I2S_ClearFlag(SPI1, SPI_I2S_FLAG_RXNE);
   // delay
   Delay(0x7FFFF);
   while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) != SET);
   SPI_I2S_SendData(SPI1, (u8)data);
   while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) != SET);
   Delay(0x7FFFF);
   spiData = (u8)(SPI_I2S_ReceiveData(SPI1));
   // bring chip select high
   GPIO_SetBits(GPIOA, GPIO_Pin_4); // pull low to enable SPI
   return spiData;

}

int main(void) {
  unsigned int adc1, adc2, adc3, adc4 = 0;
  double temp1, temp2, humid1, humid2 = 0;
  unsigned int PIR1, PIR2 = 0;
  unsigned int spiData;

  /* configure clock sources */
  RCC_Configuration();

  /* configure I/O ports */
  GPIO_Configuration();

  /* ADC1 init */
  InitADC1();
  printf("Starting program...\r\n");
  /* blinking loop */
  while (1) {
    /* SPI comm */
   spiData = 0xFF;
   while (spiData != 0xAF) {
      spiData = readSPI((u8)0xc0);
      printf("SPI Data - 0xc0:\t0x%x\r\n", spiData);
   }
   spiData = readSPI(0xa0);
   printf("SPI Data - 0xa0:\t0x%x\r\n", spiData);
   spiData = readSPI(0xb0);
   printf("SPI Data - 0xb0:\t0x%x\r\n", spiData);
   /* read adc */
   adc1 = GetADC1Channel(ADC_Channel_1, 3); // humid
   adc2 = GetADC1Channel(ADC_Channel_2, 3); // temp
   adc3 = GetADC1Channel(ADC_Channel_3, 3); // ref
   adc4 = GetADC1Channel(ADC_Channel_17, 3); // ref
    PIR1 = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_15);
   //if (PIR1) GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET); else GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
   temp1 = (int)(((((double)adc2/(double)adc3)*100) / 100) * 75) - 15;
   humid1 = (int)(((double)adc1/(double)adc3)*100);
   if (temp1 != temp2 || humid1 != humid2 || PIR1 != PIR2) {
      temp2 = temp1;
      humid2 = humid1;
      PIR2 = PIR1;
      printf("ADC Values\r\n");
      printf("\tRef:\t%d\r\n", adc3);
      printf("\tTemp:\t%d\r\n", adc2);
      printf("\tHumid:\t%d\r\n", adc1);
      printf("\tInternal:\t%d\r\n", adc4);
      printf("Calculated values\r\n");
      printf("\tTemp:\t%.2f\r\n", temp1);
      printf("\tHumid:\t%.2f\r\n", humid1);
      printf("\tPIR:\t%d\r\n", PIR1);
      printf("\r\n\r\n");
   }
    Delay(0x5FFFF); // wait for a while
  }
}
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo
urosg
Član
Član



Pridružen-a: Pet 27 Apr 2007 14:30
Prispevkov: 565
Aktiv.: 2.56

PrispevekObjavljeno: Tor Avg 09, 2011 7:49 pm    Naslov sporočila:   Odgovori s citatom

Eno napako sem ze nasel in sicer mora biti CPOL na High in ne na Low kot je v kodi.

Sedaj so podatki ze v pravi obliki oz. vrednostih, samo se "zamik" moram urediti. Ker mi IDLE status vrne 2x.
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo
aly
Član
Član



Pridružen-a: Tor 28 Sep 2004 14:51
Prispevkov: 9407
Aktiv.: 39.75
Kraj: Kranj - struževo

PrispevekObjavljeno: Tor Avg 09, 2011 9:40 pm    Naslov sporočila:   Odgovori s citatom

Ravno to sem hotel pokomentirati - pazi da imaš polariteto in fazo pravilno nastavljeno. Sicer lahko dobivaš naključne rezultate ali zamaknjene za en bit.

hint: Osciloskop Wink

Namesto da na roke preklapljaš CS signal lahko za to uporabbiš NSS signal, ki je hardversko krmiljen. Tole spremeni:
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;

_________________
I'm going to stand outside, so if anyone asks, I'm outstanding Smile
Nazaj na vrh
Skrit Poglej uporabnikov profil Pošlji zasebno sporočilo Obišči avtorjevo spletno stran MSN Messenger - naslov
Pokaži sporočila:   
Objavi novo temo   Odgovori na to temo   Printer-friendly version    www.elektronik.si Seznam forumov -> ARM arhitektura Časovni pas GMT + 2 uri, srednjeevropski - poletni čas
Stran 1 od 1

 
Pojdi na:  
Ne, ne moreš dodajati novih tem v tem forumu
Ne, ne moreš odgovarjati na teme v tem forumu
Ne, ne moreš urejati svojih prispevkov v tem forumu
Ne, ne moreš brisati svojih prispevkov v tem forumu
Ne ne moreš glasovati v anketi v tem forumu
Ne, ne moreš pripeti datotek v tem forumu
Ne, ne moreš povleči datotek v tem forumu

Uptime: 486 dni


Powered by phpBB © 2001, 2005 phpBB Group