Cortex-m3m4 çalışan kütüphane-driver Kodları

Başlatan mcan, 24 Kasım 2011, 22:58:14

mcan

Selam burada ,arm cortex için yazdığım-bulduğum çalıştırıp denediğim kütüphane-driver tarzındaki kodları paylaşmayı planlıyorum.ccs  den alıntısını yapıp keilde cortex m3 için uyarladığım "karakter lcd" kodunu kullanabilirsiniz.
Nette bulabileceğiniz flexy lcd tarzdaki kodlara benziyor tek flexy olmayan yanı data pinlerini kendi içinde ayrı ayrı tanımlanamıyor.Aslında koda bakıp o kısmını değiştirebilirsiniz ancak hızlı deneme yapmak için bu kadarını yazdım...

Lcd_d.c
#ifndef	Lcd_Rs_Port
	#define Lcd_Rs_Port		GPIOB_BASE
	#define Lcd_Rs_Pin		9
	#define Lcd_Rw_Port		GPIOB_BASE
	#define Lcd_Rw_Pin		10
	#define Lcd_Enable_Port	GPIOB_BASE
	#define Lcd_Enable_Pin	11
	#define Lcd_Data_Port	GPIOB_BASE
	#define Lcd_Data_Pin1	12
#endif


#define ODR_	0x0C	//GPIO output register
#define IDR_	0x08	//GPIO input  register
#define CR_		0x00	//GPIO Mode  register

#define Lcd_Data_InPort		(Lcd_Data_Port+IDR_	)
#define Lcd_Data_OutPort	(Lcd_Data_Port+ODR_	 )

#define BIT_LEVEL_SRAM(a,b) ((SRAM_BB_BASE + (a-SRAM_BASE)*32 + (b*4)))
#define BIT_LEVEL_PERI(a,b) ((PERIPH_BB_BASE + (a-PERIPH_BASE)*32 + (b*4)))
 
#define Lcd_Rw		*((volatile unsigned int *)(BIT_LEVEL_PERI((Lcd_Rw_Port+ODR_),Lcd_Rw_Pin))) //Bitband access rw pin
#define Lcd_Rs		*((volatile unsigned int *)(BIT_LEVEL_PERI((Lcd_Rs_Port+ODR_),Lcd_Rs_Pin))) //Bitband access rs pin
#define Lcd_Enable	*((volatile unsigned int *)(BIT_LEVEL_PERI((Lcd_Enable_Port+ODR_),Lcd_Enable_Pin))) //Bitband access enable pin
	
   
typedef struct{
	int 		    : Lcd_Data_Pin1;	// on to an I/O port to gain
    int	data_pins	: 4;         		// access to the LCD pins.

} LCD_X ;
  
typedef struct{              
	__IO	uint32_t 				: Lcd_Data_Pin1*4;	//o
	__IO    uint32_t	data_pins	: 16;         		// access to the LCD data pins mode.
} LCD_Data_mode ;

typedef struct{              
	__IO	uint32_t 		 : Lcd_Rs_Pin*4;	// o
	__IO    uint32_t 	mode : 4;         		// access to the LCD Rs pins.
} LCD_Rs_ ;

typedef struct{              
	__IO	uint32_t 		 : Lcd_Rw_Pin*4;	// o
	__IO    uint32_t 	mode : 4;         		// access to the LCD pins.
} LCD_Rw_ ;

typedef struct{              
	__IO	uint32_t 		 : Lcd_Enable_Pin*4;         // on to an I/O port to gain
	__IO    uint32_t 	mode : 4;         // access to the LCD pins.
} LCD_Enable_ ;

void delay_us(unsigned int);

#define Lcd_Out ((LCD_X *)(Lcd_Data_OutPort))
#define Lcd_In ((LCD_X *)(Lcd_Data_InPort))
#define Lcd_Mode	((LCD_Data_mode *)(Lcd_Data_Port+CR_))
#define Lcd_Rs_mode	((LCD_Rs_ *)(Lcd_Rs_Port+CR_))
#define Lcd_Rw_mode	((LCD_Rw_ *)(Lcd_Rw_Port+CR_))
#define Lcd_Enable_mode	((LCD_Enable_ *)(Lcd_Enable_Port+CR_))

#define All_input	0x4444	//Data pins input setting
#define All_output	0x3333	//Data pins output 50Mhz setting
#define Pin_output	0x3		//X pins output 50Mhz setting
#define delay_cycles(x)	delay_us(x)

#define lcd_type 2           // 0=5x7, 1=5x10, 2=2 lines
#define lcd_line_two 0x40    // LCD RAM address for the second line



char const LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6};// These bytes need to be sent to the LCD to start it up.


 

char lcd_read_byte() {
	char low=0,high=0;
	Lcd_Mode->data_pins = All_input;	//set_tris_lcd(LCD_READ);
    Lcd_Rw = 1;
	delay_cycles(1);
    Lcd_Enable = 1;
	delay_cycles(1);
    high = Lcd_In->data_pins;
    Lcd_Enable = 0;
	delay_cycles(1);
    Lcd_Enable = 1;
    delay_us(1);
    low = Lcd_In->data_pins;
    Lcd_Enable = 0;
	Lcd_Mode->data_pins = All_output;
    return( (high<<4) | low);
}


void lcd_send_nibble( char n ) {
	Lcd_Out->data_pins = n ;
	delay_cycles(1);
    Lcd_Enable = 1;
    delay_us(2);
    Lcd_Enable = 0;
}


void lcd_send_byte( char address, char n ) {
	
	char lcd_timeout = 0;
	
	Lcd_Rs = 0;
    while ( (lcd_read_byte()&0x80) )
    {
		if(lcd_timeout>10)
        	break;
        else
            lcd_timeout++;
         
    }
    Lcd_Rs = address;
	delay_cycles(1);
    Lcd_Rw = 0;
	delay_cycles(1);
    Lcd_Enable = 0;
    lcd_send_nibble(n >> 4);
    lcd_send_nibble(n & 0xf);
}


void lcd_init(void) {
	char i;
	Lcd_Mode->data_pins = All_output;
	Lcd_Rs_mode->mode = Pin_output;
	Lcd_Rw_mode->mode = Pin_output;
	Lcd_Enable_mode->mode = Pin_output;

    Lcd_Rs = 0;
    Lcd_Rw = 0;
    Lcd_Enable = 0;
    delay_us(15000);
    for(i=1;i<=3;++i) {
       lcd_send_nibble(3);
       delay_us(5000);
    }
    lcd_send_nibble(2);
    for(i=0;i<=3;++i)
       lcd_send_byte(0,LCD_INIT_STRING[i]);
}

						 
void lcd_gotoxy( char x, char y) {
   char address;

   if(y!=1)
     address=lcd_line_two;
   else
     address=0;
   address+=x-1;
   lcd_send_byte(0,0x80|address);
}

int lcd_putc( char c) {
   switch (c) {
     case '\f'   : lcd_send_byte(0,1);
                   delay_us(2000);
                                           break;
     case '\n'   : lcd_gotoxy(1,2);        break;
     case '\b'   : lcd_send_byte(0,0x10);  break;
     default     : lcd_send_byte(1,c);     break;
   }
   return(0);
}


char lcd_getc( char x, char y) {
   char value;

	lcd_gotoxy(x,y);
    while ( (lcd_read_byte()&0x80) ); // wait until busy flag is low
    Lcd_Rs =1;
    value = lcd_read_byte();
    Lcd_Rs =0;
    return(value);
}


Kodu denemek için örnek program kodu,
#include "STM32F10x.h"
#include <stdio.h>
//#include "Registers.h"
#include "Lcd_d.c"
#include "Retarget.c"


static int ih;
int zg,ipb,ii;


void TIM7_IRQHandler(void)
{	
    ih =!ih ;

    while(TIM7->SR)
    {
        TIM7->SR  = 0x0;
    }
    
}

void delay_us(unsigned int i)
{   unsigned int z,y;
    for(z=0;z<i;z++)
	{
		for(y=0;y<8;)
		{
			y++;
		}	
	}
}

void delay_zs(unsigned int i)
{   unsigned int z,y;
    for(z=0;z<i;z++)
	{
		for(y=0;y<5;)
		{
			y++;
		}	
	}   
}

void SystemInit (void)
{
    delay_zs(88000);
 	RCC->APB2ENR |= 0x00000018;    // GPIOD donaniminin clock sinyalini uygulayalim
    GPIOC->CRL = 0x37333333;     // GPIOD nin 15, 14, 13, 12 pinleri cikis tanimlandi (Ledler bu pinlerde)
    GPIOC->CRH = 0x33333333;

    RCC->CR |= 0x0010000;	   			// HSE ON
    RCC->CFGR = 0x001D0000;	   			// PLL ayarla
    RCC->CR  |= 0x001000000;	   		// PLL aç
    FLASH->ACR =  0x32;					// Flash gecikme ayari
    RCC->CFGR = 0x001D0702;	   			// SINYAL KAYNAGI PLL	 APB1 HCLK/16

    RCC->APB1ENR |= 0x00000020;		    //Timer7 ye clock verelim
    TIM7->DIER = 0x1;
    TIM7->PSC = 0x1FF;			  		//182=B6  182*5= H393
    TIM7->ARR = 0xFFFF;
    TIM7->CR1  = 0x85;
	NVIC->ISER[1] = 0X00800000;        // NVIC de Timer 7 interrupta izin verelim

} 
                                                                                                           


 
int main()
{
	lcd_init();
	lcd_putc('\f');
	printf("\fOldu sonunda\nTesekkurler");

    while(1)
   {
     if(ih)
     	GPIOC->ODR= 0x00000200;		//GPIOC->ODR= 0x20;     // Ledler yansin
     else
        GPIOC->ODR= 0x00000020;		//GPIOC->ODR= 0x200;     // Ledler yansin
     delay_us(250000);
     GPIOC->ODR= 0x00000000;     // Ledler sonsun
     delay_us(250000);
   } 
}


Delay_us tam olarak çalışmıyordur çünki telefonun kronometresi ile kalibre etmeye çalıştım.
Ayrıca printf için şu koda ihtiyacınız olacak ,yardımından dolayı özellikle @Gerbay a teşekkürler.

Retarget.c
struct __FILE{
	char c;
};

FILE __stdout; // linker hatasi vermemesi icin gerekli
FILE __stdin;
FILE __stderr;

int fputc(int ch, FILE *f) 
{
  return (lcd_putc((char)ch));
}

int ferror(FILE *f) 
{
  // ...
  return EOF;
} 

/*void _ttywrch(int ch) 
{
  lcd_putc(ch);
}

void _sys_exit(int return_code) 
{
  label:  goto label;  // sonsuz döngü
} */


Kütüphanede kullanılan lcd pinlerini değiştirmek için

    #define Lcd_Rs_Port      GPIOB_BASE
    #define Lcd_Rs_Pin      9
    #define Lcd_Rw_Port      GPIOB_BASE
    #define Lcd_Rw_Pin      10
    #define Lcd_Enable_Port   GPIOB_BASE
    #define Lcd_Enable_Pin   11
    #define Lcd_Data_Port   GPIOB_BASE
    #define Lcd_Data_Pin1   12
Kısmını istediğiniz port ve pine göre tanımlayın. LCD data pinlerinin ilki 12. GPIOB pinine denk geliyor, Yani 12-13-14-15 LCD data pinleri ,  lcd rs pini ise 9. pin. Ayrıca eğer lcd 5v ile çalıyorsa portu  ve pinleri tanımlarken pinlerin 5 volt toleranslı olmasına dikkat edin .

mcan

Bu gun iki dosyayi daha uyarladim, one wire iletisim ve ds18b20 kodlari...

One wire.c
#define onewire_Port		GPIOB_BASE //portu pini burda
#define onewire_Pin			5                   // tanimliyoruz

#define ODR_	0x0C
#define IDR_	0x08	
#define CR_	0x00	

#define onewire_Data_In		(onewire_Port+IDR_)
#define onewire_Data_Out	(onewire_Port+ODR_)

#define BIT_LEVEL_SRAM(a,b) ((SRAM_BB_BASE + (a-SRAM_BASE)*32 + (b*4)))
#define BIT_LEVEL_PERI(a,b) ((PERIPH_BB_BASE + (a-PERIPH_BASE)*32 + (b*4)))

typedef struct{              
	__IO	uint32_t 		: onewire_Pin*4;
	__IO    uint32_t	pin	: 4;         		
} onewire_mode ;

#define ONE_WIRE_INPUT		*((volatile unsigned int *)(BIT_LEVEL_PERI(onewire_Data_In,onewire_Pin)))
#define ONE_WIRE_OUTPUT		*((volatile unsigned int *)(BIT_LEVEL_PERI(onewire_Data_Out,onewire_Pin))) 
#define ONE_WIRE_MODE		(*((onewire_mode *)(onewire_Port+CR_))).pin

#define	PushPull_out50Mhz  	3
#define	Float_in  			4

/*#define ONE_WIRE_INPUT PortB.Input.Pin5
#define ONE_WIRE_OUTPUT PortB.Output.Pin5
#define ONE_WIRE_MODE PORTB.Mode.Pin5  */
/*******************1-wire communication functions********************/ 

/************onewire_reset*************************************************/ 
/*This function initiates the 1wire bus */ 
/* */ 
/*PARAMETERS: */ 
/*RETURNS: */ 
/*********************************************************************/ 

void onewire_reset()  // OK if just using a single permanently connected device 
{ 
 ONE_WIRE_OUTPUT = 0 ;
 ONE_WIRE_MODE = PushPull_out50Mhz; 
 delay_us( 500 ); // pull 1-wire low for reset pulse 500
 ONE_WIRE_MODE = Float_in; // float 1-wire high 
 delay_us( 500 ); // wait-out remaining initialisation window. 500
 ONE_WIRE_MODE = Float_in; 
}

/*********************** onewire_write() ********************************/ 
/*This function writes a byte to the sensor.*/ 
/* */ 
/*Parameters: byte - the byte to be written to the 1-wire */ 
/*Returns: */ 
/*********************************************************************/ 



void onewire_write(char data) 
{ 
 char count; 

 for (count=0; count<8; ++count) 
 { 
	ONE_WIRE_OUTPUT = 0 ;
	ONE_WIRE_MODE = PushPull_out50Mhz;  
  	delay_us( 2 ); // pull 1-wire low to initiate write time-slot. 2
	ONE_WIRE_OUTPUT = (data&0x01);
	data >>= 1;
  	delay_us( 60 ); // wait until end of write slot. 60
  	ONE_WIRE_MODE = Float_in; 
  	delay_us( 2 ); // for more than 1us minimum. 2
 } 
}
/*********************** read1wire() *********************************/ 
/*This function reads the 8 -bit data via the 1-wire sensor. */ 
/* */ 
/*Parameters: */ 
/*Returns: 8-bit (1-byte) data from sensor */ 
/*********************************************************************/ 

char onewire_read() 
{ 
 char count, data=0; 

 for (count=0; count<8; ++count) 
 { 
  	ONE_WIRE_OUTPUT = 0 ;
	ONE_WIRE_MODE = PushPull_out50Mhz; 
  	delay_us( 2 ); // pull 1-wire low to initiate read time-slot. 2
  	ONE_WIRE_MODE = Float_in;
	data>>=1;
  	delay_us( 18 ); // let device state stabilise, 8
	if ( ONE_WIRE_INPUT==1)
		data |= 0x80;
  	delay_us( 60 ); // wait until end of read slot. 120
 } 

 return( data ); 
}



Bu dosya ise basit bicimde sicaklik okumak icin
Ds18b20.c
#define High(v) (*(((unsigned char *) (&v)+ 1)))
#define Low(v) (*((unsigned char *) (&v)))


float ds1820_read(void) 
{ 
 	signed short temp3; 
 	float result; 

 onewire_reset(); 
 onewire_write(0xCC); 
 onewire_write(0x44); 

 while (temp3 == 0) 
  temp3 = onewire_read(); 

 onewire_reset(); 
 onewire_write(0xCC); 
 onewire_write(0xBE);
 Low(temp3) = onewire_read(); 
 High(temp3) = onewire_read();

 //result = (float) temp3 / 2.0;   //Calculation for DS18S20 with 0.5 deg C resolution 
 result = (float) temp3 / 16.0;  //Calculation for DS18B20 with 0.1 deg C resolution
 return(result); 
}


Ornek ;
main c
#include "STM32F10x.h"
#include <stdio.h>
#include "Registers.h"
#include "Lcd_d.c"
#include "Retarget.c"
#include "one_wire.c"
#include "DS1820_.c"


static int ih;

void TIM7_IRQHandler(void)
{
		
    ih =!ih ;

    while(TIM7->SR)
    {
        TIM7->SR  = 0x0;
    }
    
}

void delay_us(unsigned int i)
{   unsigned int z,y;
    for(z=0;z<i;z++)
	{
		for(y=0;y<8;)
		{
			y++;
		}	
	}
}

void delay_zs(unsigned int i)
{   unsigned int z,y;
    for(z=0;z<i;z++)
	{
		for(y=0;y<5;)
		{
			y++;
		}	
	}   
}

void SystemInit (void)
{
    delay_zs(88000);
 	RCC->APB2ENR |= 0x00000018;    // GPIOD donaniminin clock sinyalini uygulayalim
    GPIOC->CRL = 0x37333333;     // GPIOD nin 15, 14, 13, 12 pinleri cikis tanimlandi (Ledler bu pinlerde)
    GPIOC->CRH = 0x33333333;

    RCC->CR |= 0x0010000;	   			// HSE ON
    RCC->CFGR = 0x001D0000;	   			// PLL ayarla
    RCC->CR  |= 0x001000000;	   		// PLL aç
    FLASH->ACR =  0x32;					// Flash gecikme ayari
    RCC->CFGR = 0x001D0702;	   			// SINYAL KAYNAGI PLL	 APB1 HCLK/16

    RCC->APB1ENR |= 0x00000020;		    //Timer7 ye clock verelim
    TIM7->DIER = 0x1;
    TIM7->PSC = 0x1FF;			  		//182=B6  182*5= H393
    TIM7->ARR = 0xFFFF;
    TIM7->CR1  = 0x85;
	//NVIC->ISER[1] = 0X00800000;        // NVIC de Timer 7 interrupta izin verelim

} 
                                                                                                           

 
int main()
{
	char ss=0;
	lcd_init();

    while(1)
   {
   	 ss++;
     if(ih)
     	GPIOC->ODR= 0x00000200;		//GPIO->ODR= 0x20;     // Ledler yansin
     else
        GPIOC->ODR= 0x00000020;		//GPIO->ODR= 0x200;     // Ledler yansin
     delay_us(250000);
     GPIOC->ODR= 0x00000000;     // Ledler sonsun
     delay_us(250000);

	 if(ss==3)
	 {
	 	printf("\fTemp:%f3.1",ds1820_read());
		ss=0 ;
	 }
   } 
}


CortexM4 icin kitler geldiginde uyarlamaya calisicam.