STM32F10X Çalışmalarım

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

Mucit23

Hocam USART->SR->TC ye ulaşamıyorum.

while (!USART->SR->TC){} Bu şekilde bir kullanım yanlışmı?

SRC\main.c(104): error:  #20: identifier "USART" is undefined

USART diye birşey tanımlı değil diyor. Bu registerin TC bitine nasıl ulaşırım

Klein

#91
Eğer tek karakter göndereceksen TC bitini bekleyebilrsin. Peşpeşe birden fazla karakter göndereceksen TXE bitini beklemen gerek.  Eğer RS485 kullanmıyorsan TC bitini beklemene gerek yok. RS485 kullanacaksan eğer karakter aralarında TXE bitini , tüm karakterlerin gönderimi bittikten sonra , RS485 çipini alma moduna getirmek için TC bitini beklemen gerek.

while(!(USART3->SR&0x80)); //TXE biti.  
TC bitinin hangi bit olduğunu  hatırlamıyorum.
 

https://www.picproje.org/index.php/topic,43180.0.html

Eğer kütüphane kullanıyorsan

USART_GetFlagStatus(USART3,USART_Flags_TXE)
USART_GetFlagStatus(USART3,USART_Flags_TC)

Ekleme:
TC biti SR registerinin 6. biti imiş.
while(!(USART3->SR&0x40)); //TC biti. 
 

Mucit23

Klein Hocam Merhabalar.

Bugün Sizin STM32F4 DMA+ADC örneğinizden yola çıkarak Aynısını stm32f1x de  iki kanal için yapmaya çalıştım.

Yaptığım ayarlamalar şöyle.
#include "stm32f10x_lib.h"

void  initADC1(void);
void  ADC1_DMAConfig(void);
void  adc_channel_config(void);
u16 readADC1(u8 channel);
u8 ADC1H(u8 channel); /*Okunan ADC kanalinin yuksek degerlikli 8 bitini donderir*/
u8 ADC1L(u8 channel); /*Okunan ADC kanalinin dusuk degerlikli 8 bitini donderir*/

u16 ADC_DMAValue[2];

/*ADC baslanagic ayarlari yuklenme islemini yapar */
void initADC1(){
				ADC_InitTypeDef ADC_InitStructure;
				RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);
				/* ADC pin analog input yapiliyor */
				GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;  
				GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
				GPIO_Init(GPIOA, &GPIO_InitStructure);

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

				ADC_Cmd(ADC1, ENABLE);

				/* ADC1 Reset Kalibrasyonu yapilacak */
				ADC_ResetCalibration(ADC1);
				/* Kalibrasyon bekleniyor */
				while(ADC_GetResetCalibrationStatus(ADC1));

				/* ADC1 calibrasyonu yapilacak */
				ADC_StartCalibration(ADC1);
				/* Kalibrasyon bekleniyor */
				while(ADC_GetCalibrationStatus(ADC1));
}
//1. Adc Modülü DMA Ayarlari...
void ADC1_DMAConfig(void){
  DMA_InitTypeDef DMA_InitStructure;
  
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);                           //DMA Saat girisi Aktif Ediliyor..

  DMA_Cmd(DMA1_Channel1,DISABLE);
  DMA_DeInit ( DMA1_Channel1);

  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)0x4001244C;            // ADC->DR Adresi
  DMA_InitStructure.DMA_MemoryBaseAddr = (u32) ADC_DMAValue;                     // hedef adresimiz
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;                          // ADC kaynak. Veri yönü ADC -> Hafiza 
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;            // ADC adresi sabit kalacak
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                     // Her deger alindigina memory adresi 1 artirilacak
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // Kaynaktan alinacak veri 16 bit
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;         // Hedef büyüklügü 16 bit
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;                             // 8 veri alindiktan sonra basa dönülecek.
  DMA_InitStructure.DMA_Priority = DMA_Priority_High ;                        // Kanal Önceligi yüksek. ( bu bize kalmis)
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                                // hafizadan hafizaya transfer kapali. 
  DMA_InitStructure.DMA_BufferSize = 2;                                       // Alacagimiz verisayisi 2 ( 2 kanal adc okuyacagiz) 
  
  DMA_Init(DMA1_Channel1, &DMA_InitStructure);
  DMA_Cmd(DMA1_Channel1,ENABLE);
}

void adc_channel_config(void){
    ADC_RegularChannelConfig(ADC1,ADC_Channel_0, 1, ADC_SampleTime_239Cycles5);
    ADC_RegularChannelConfig(ADC1,ADC_Channel_1, 2, ADC_SampleTime_239Cycles5);
}

u16 readADC1(u8 channel){
		u16 adc=0;
		ADC_RegularChannelConfig(ADC1, channel, 1, ADC_SampleTime_55Cycles5);
		/* Adc dönüsümü baslatiliyor */
		ADC_SoftwareStartConvCmd(ADC1, ENABLE);
		/* Adc dönüsümü bekleniyor */
		while(ADC_GetSoftwareStartConvStatus(ADC1));
		/* Adc sonucu okunuyor */
		adc=ADC_GetConversionValue(ADC1);
		return adc;
}

u8 ADC1L(u8 channel){
		u8 adc_low=0xFF&readADC1(channel);
		return adc_low;
}

u8 ADC1H(u8 channel){
		u16 temp=0xFF00&readADC1(channel);
		u8 adc_high=temp>>8;
		return adc_high;
}


Normalde readADC1 fonksiyonu ile adc değerini okuyabiliyorum ama DMA ile bu iş olmadı. Oluşturduğumuz diziden sürekli 2-3-4 değerleri geliyor.

Main içerisinde tüm ayarlamaları yapıyorum.
adc_channel_config();
		 initADC1();
		 ADC1_DMAConfig();
		 ADC_DMACmd(ADC1,ENABLE);
		 ADC_SoftwareStartConvCmd(ADC1,ENABLE);


okurkende ADC_degeri=ADC_DMAValue[0]; gibi bir komutla dizideki değeri alıyorum.

Şunda şüpheleniyorum Acaba ADC_DR değerimi yanlış. Normalde siz ADC_Dr için 0x4001244C  değerini vermiştiniz. STM32F107 nin datasheetinde ADC DR ofset değeri 0x4C olarak belirtilmiş.

Sıkıntı nerde olabilir?

Klein

Yok onunla ilgili değil. DR registerinin offseti 4C doğru. Verdiğim adresin sonuna bakarsan 4C olduğunu görürsün. Gerisi ADC1'in base adresi.
Yayınladığım örnek zaten STM32F1x için.  Hiç değişiklik yapmadan,sadece kanal sayısını düşürerek çalıştırabilirsin.

örnek uygulamada
main içerisinde init_gpio() ve init_rcc()  görünmüyor. Muhtemelen başka bir yerde init ettiğim için veya buraya aktarırken yanlışlıkla kestiğim için görünmüyor.  Önce GPIO ve RCC init ediliyor. sonra ADCve DMA initleri yapılıyor.

Senin uygulamada  RCC ve GPIO initleri "initADC1()" rutiniiçerisinden yapılıyor. Ancak bu rutini çağırmadan önce "adc_channel_config()" rutinini çağırdığın için , muhtemelen bu registerlere yazma yapamıyorsun.   ikisinin yerini değiştirirsen veya, RCC ve GPIO initlerini başka bir rutine alıp nceden çağırırsan sorun çözülecektir.

Örneği de düzeltiyorum.

Mucit23

Klein Hocam merhaba.

Kaç gündür yazamıyordum. Sorun dediğiniz gibiymiş.

Yapmak istediğim birşey daha var. Sizin fikrinizi almak isterim.

Normalde ADC den aldığım değerlerin aritmetik ortalamasını alıyorum. Her bir seferinde n kadar ADC değerine bakıp aldığım değerleri toplayıp n' e bölüyorum. Bu işlem vaktimi alıyor.

DMA modülü, diyelim aynı adc kanalından N kadar örnek alıp bu örnekleri bir diziye yerleştirebilirmi? Ben main içerisinde sadece bu dizideki değerleri toplayıp örnek sayısına bölerek ham adc değerini elde edeyim.

Klein

#95
ADC'yi tek kanal kullanırsan olur
DMA_InitStructure.DMA_BufferSize = 2;
Bu rakamı kullanmak istediğin tamponun büyüklüğü kadar yaparsan olur.

Bunun yerine, Özellikle çok kanal kullanıyorsan; moving averaj kullanmanı öneririm. Daha az zaman harcarsın, verin daha hızlı güncellenir.

Örnek:
#define  ADC_COUNT 8
#define  FILTERSIZE 512

typedef struct{
	uint16_t Buf[FILTERSIZE];
	uint32_t Total;
	uint16_t FilterIndex;
	float Value;
}AdFilter_TypeDef;

AdFilter_TypeDef AdFilter[ADC_COUNT];
uint16_t FilterIndex;
uint16_t volatile adc_values[ADC_COUNT]; // ADC değerlerinin alındığı tampon. 
uint16_t volatile AdcConverted=0;

void ADCCalculate(void){
uint16_t temp2;
static uint16_t index=0;

/***********************   Kayan ortalama **************************************************/
		  AdFilter[index].Total -=  AdFilter[index].Buf[AdFilter[index].FilterIndex];
		  AdFilter[index].Total += adc_values[index];
		  AdFilter[index].Buf[FilterIndex]=adc_values[index];

		  temp2 = AdFilter[index].Total / (FILTERSIZE);
/***************************************************************************************/

		  if(++AdFilter[index].FilterIndex == FILTERSIZE)
		  {
			  AdFilter[index].FilterIndex=0;
		  }
		  if(++index == ADC_COUNT) 
		  {
			  index=0;
			  AdcConverted=0;
			  if(++FilterIndex == FILTERSIZE)
			  {
				  FilterIndex=0;
			  }
		  }
}


int main(void)
{
..
..
..
while (1)
  {
	if(AdcConverted) ADCCalculate();
             ..
             ..
  }
}

Mucit23

Arkadaşlar Merhaba

keil de bool tipi bir değişken tanımlayıp bu değişkene 1 veya 0 bitlik bir değer atadığım zaman aşağıdaki uyarıyı alıyorum.

SRC\main.c(91): warning:  #188-D: enumerated type mixed with another type


Ayrıca Yine Sprintf, ABS, memcpy gibi fonksiyonları kullandığım zaman aşağıdaki yarılardan alıyorum.

SRC\main.c(52): warning:  #223-D: function "sprintf" declared implicitly


Kodun çalışmasına engel olmuyorlar ama neden böyle bir uyarı veriyor.

ErsinErce

#97
bool değişkeni için ansi c için aşağıdaki kütüphaneyi kullanabilirsiniz
içeriği gerbay hocamın verdiği kodların benzeri şekilde

#include <stdbool.h>


içeriğine bakmak isterseniz adresi ..\Keil\ARM\ARMCC\include\



ayrıca başka bir çözüm olarak;

http://www.eosgarden.com/en/articles/bool/

SpeedyX

#define FALSE 0
#define TRUE (!FALSE)

Mucit23

hocam Teşekkür ederim. Uyarıların büyük çoğunluğunu hallettim. Sadece ABS fonksiyonu için bir uyarı veriyor.

Stdio.h ekli durumda

SRC\main.c(84): warning:  #223-D: function "abs" declared implicitly

ErsinErce

oda math.h içinde olması lazım

Mucit23

yok hocam denedim math.h da yok.

ErsinErce


Mucit23

Ersin Hocam Teşekkür ederim.

Bu kütüphane dosyasını eklemeden neden sadece uyarı alıyorum. Hata almam gerekmezmi?

ErsinErce

o konuyu bilmiyorum otomatik ekleme tarzı birşeyler olabilir
gerbay hocayı yakalayınca sormak lazım cevabını büyük ihtimal biliyordur diye umuyorum