 |
www.elektronik.si Forum o elektrotehniki in računalništvu
|
Poglej prejšnjo temo :: Poglej naslednjo temo |
Avtor |
Sporočilo |
urosg Član


Pridružen-a: Pet 27 Apr 2007 14:30 Prispevkov: 565 Aktiv.: 2.56
|
Objavljeno: Tor Avg 09, 2011 8:43 am Naslov sporočila: STM32 in SPI komunikacija |
|
|
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 |
|
 |
aly Član



Pridružen-a: Tor 28 Sep 2004 14:51 Prispevkov: 9407 Aktiv.: 39.75 Kraj: Kranj - struževo
|
Objavljeno: Tor Avg 09, 2011 9:55 am Naslov sporočila: |
|
|
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  |
|
Nazaj na vrh |
|
 |
urosg Član


Pridružen-a: Pet 27 Apr 2007 14:30 Prispevkov: 565 Aktiv.: 2.56
|
Objavljeno: Tor Avg 09, 2011 7:23 pm Naslov sporočila: |
|
|
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 |
|
 |
urosg Član


Pridružen-a: Pet 27 Apr 2007 14:30 Prispevkov: 565 Aktiv.: 2.56
|
Objavljeno: Tor Avg 09, 2011 7:49 pm Naslov sporočila: |
|
|
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 |
|
 |
aly Član



Pridružen-a: Tor 28 Sep 2004 14:51 Prispevkov: 9407 Aktiv.: 39.75 Kraj: Kranj - struževo
|
Objavljeno: Tor Avg 09, 2011 9:40 pm Naslov sporočila: |
|
|
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
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  |
|
Nazaj na vrh |
|
 |
|
|
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
|