Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Split Numbers

Status
Not open for further replies.
I didn't know it will automatically link them ... that's cool. I don't want to be a bother but im away from my pc right now and can't check it... how would I make/use externs?
 
You use extern to define a reference to a variable declared outside of the module.

extern int foo;

in one module, it needs to be declared.
int foo;

any C Reference will give you the details and some PIC compilers do things differently so check the manual.
 
for some reason i get errors... Some questions:

1. Do i have to include header in each c file?
2. How do i extern a #define?

Can someone show me some examples of this. I hate the c18 manual it sux. No good info in it.

3. Anyone got a better resource than the c18 manual?
 
for some reason i get errors... Some questions:

1. Do i have to include header in each c file?
2. How do i extern a #define?

Can someone show me some examples of this. I hate the c18 manual it sux. No good info in it.

3. Anyone got a better resource than the c18 manual?

If I remember the rest of the thread you are doing separate compiles then linking. If a C file needs info from a header file you have to include the header file. Well written header files have a check in the form of #ifdef myFlagName that will prevent them from generating errors if included twice.

You do not do extern #defines, you include the header file in which they exist.

The things you are talking about are general C related issues. So the BoostC or C18 linker and complier docs would be more helpful. Maybe a general C book like K&R C. Most of what you want is going to be buried in a lot of other stuff. Maybe a section on linking objects would have some of it.

I would like to provide more info but I have to run. Mike or one of the others can fill in the details, if not I will be back in a few hours.
 
there is no such thing as an extern for #defines. An extern is a message for the linker, #define is actually a preprocessor directive that caused the defined string to textually substituted before the compiler is actually run. #defined names actually don't exist to the compiler itself. By the way, all # lines are preprocessor directives. Even #include...

Take all your #defines and put them in .h files. Separate them into logical groupings - serial I/O ones in serial.h, LCD ones in lcd.h. I would include the function prototypes in the relevant .h. Then #include the relevant .h files in the .c files that reference them. I'd put together a simple example but I've got to go earn a buck...
 
Last edited:
Thanks a bunch... that seems to make sense.. I mean organizing it. That's the whole reason I want to split it so I can reuse it without issue. Thanks again... I make a buck tommorow.(off today)
 
here is a pic of it still working on adding 1 more button tho.
btn01 = mode/enter
btn02 = change
btn03 = enter

i want to put enter button seperate lol

picture-008-jpg.22309
 

Attachments

  • Picture 008.jpg
    Picture 008.jpg
    39.2 KB · Views: 201
lol I will ... I told you I build an expesive clock lol but its a same and since its in C and im bit banging l2C I can port it over easily.

Edit: and use a smaller pic lol. I have the DS1337 on the other side ill take a pic as soon as I get home. Im out getting some breakfast.
 
Last edited:
here is the full source with some new fixes.
FIXES (major):
When setting time it skipped # 9 (fixed)
When setting time it started @ 0 (fixed to start @ 1)

Added:
"The Time Is:" on line 1 and time on line 2

Code:
#include <p18f4525.h>
#include <stdio.h>
#include <delays.h>

#pragma config WDT = OFF, OSC = HS, LVP = OFF

void main(void);
//////////////////////////////////////////////////////
//// Delay Stuff
//////////////////////////////////////////////////////
void delay_s(unsigned char);
void delay_ms(unsigned char);
void delay_us(unsigned char);
//////////////////////////////////////////////////////
//// I2C Stuff
//////////////////////////////////////////////////////
void i2c_byte(char addr);
void i2c_start(void);
void i2c_ack(void);
char i2c_input(void);
void i2c_clock(void);
void i2c_stop(void);
//////////////////////////////////////////////////////
//// RTC Stuff
//////////////////////////////////////////////////////
char rtc_read(char offset);
char rtc_write(char offset, char data);
//////////////////////////////////////////////////////
//// LCD Stuff
//////////////////////////////////////////////////////
void lcd_clr_line(char line);
void lcd_init(void);
void lcd_cmd(unsigned char cmd);
void lcd_char(unsigned char tchar);
void lcd_string(char *);
void lcd_nybble(unsigned char data,char rs);
void e_togg(void);
//////////////////////////////////////////////////////
//// General Stuff
//////////////////////////////////////////////////////
void set_time(void);
void get_buttons(char hm);
//////////////////////////////////////////////////////
//// Variables and Defines
//////////////////////////////////////////////////////
#define SDA_PORT PORTCbits.RC4
#define SDA LATCbits.LATC4
#define SDA_TRIS TRISCbits.TRISC4
#define SCL LATCbits.LATC3
//////////////////////////////////////////////////////
//// RTC Variables
//////////////////////////////////////////////////////
char slave_r = 0b11010001;
char slave_w = 0b11010000;
//////////////////////////////////////////////////////
//// LCD Variables and Define
//////////////////////////////////////////////////////
char Line1 = 0x80;            // 0x80 is the command hex to move cursor to 0 (Line 1 first character)
char Line2 =  0xC0;            // 0xC0 is the command hex to move cursor to 64 (Line 2 first character)
#define lcd_rs LATBbits.LATB4          // define LCD RS - PIN
#define lcd_e LATBbits.LATB5           // define LCD E  - PIN
#define lcd_DB7 LATBbits.LATB0         // define LCD Data Bit 7
#define lcd_DB6 LATBbits.LATB1         // define LCD Data Bit 6
#define lcd_DB5 LATBbits.LATB2         // define LCD Data Bit 5
#define lcd_DB4 LATBbits.LATB3         // define LCD Data Bit 4
//////////////////////////////////////////////////////
//// General Variables and Defines
//////////////////////////////////////////////////////
#define up_btn PORTAbits.RA0
#define set_btn PORTAbits.RA1
//////////////////////////////////////////////////////
//// RTC Variables 
//////////////////////////////////////////////////////
char time[9] = " ";
char s_time[9] = " ";
char seconds;
char minutes;
char hours;
char g_hr_high, g_hr_low;
char g_min_high, g_min_low;
char stringA[9] = {'S','e','t',' ','H','o','u','r',0}; 
char stringB[12] = {'S','e','t',' ','M','i','n','u','t','e','s',0};
char stringC[13] = {'T','h','e',' ','T','i','m','e',' ','I','s',':',0};

void main(void)
{
    char sec_low, sec_high;
    char min_low, min_high;
    char hr_low, hr_high;
    char tmp,tmp2;


    ADCON1 = 0b00001111;
    TRISC = 0x00;
    TRISB = 0x00;
    TRISA = 0x00;
    TRISAbits.TRISA0 = 1;
    TRISAbits.TRISA1 = 1;

    lcd_init();                             //Launch Initialize function
 
    lcd_clr_line(0);
    delay_ms(50);

    lcd_cmd(Line1);                         //Set to Line 2
    delay_ms(50);

    lcd_string(stringC);                     //Send our string.
    delay_ms(60); 

    while(1){
        for(tmp=0;tmp<9;tmp++){
            time[tmp] = 0x30;
            s_time[tmp] = 0x30;
        }
    
        time[2] = 0x3A;
        time[5] = 0x3A;
        time[8] = 0;

        s_time[1] = 0x31;
        s_time[2] = 0x3A;
        s_time[5] = 0x3A;
        s_time[8] = 0;

        seconds = rtc_read(0x00);
        minutes = rtc_read(0x01);
        hours = rtc_read(0x02);

        time[7] = sec_low = (seconds & 0x0F) + '0';
        time[6] = sec_high = ((seconds>>4) & 0x0F) + '0';

        time[4] = min_low = (minutes & 0x0F) + '0';
        time[3] = min_high = ((minutes>>4) & 0x0F) + '0';

        time[1] = hr_low = (hours & 0x0F) + '0';
        time[0] = hr_high = ((hours>>4) & 0x0F) + '0';
        


	    lcd_cmd(Line2);                         //Set to Line 1
        delay_ms(1);

	    lcd_string(time);                     //Send our string.
        delay_ms(50);
    
        if(set_btn){
            set_time();
            delay_ms(50);

            rtc_write(0x00,0x00);
            s_time[0]-= 0x30;
            s_time[1]-= 0x30;
            s_time[3]-= 0x30;
            s_time[4]-= 0x30;

            tmp2 = (s_time[3]<<4) + s_time[4];
            rtc_write(0x01,tmp2);

            tmp2 = (s_time[0]<<4) + s_time[1];
            rtc_write(0x02,tmp2);

            lcd_clr_line(0);
            delay_ms(50);

            lcd_cmd(Line1);                         //Set to Line 2
            delay_ms(50);

            lcd_string(stringC);                     //Send our string.
            delay_ms(60); 
        }
   }

}

////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
////            DELAY FUNCTIONS
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////

void delay_s(unsigned char x)
{
    char var1;
	for(var1=0;var1<x;var1++)
	{
        Delay10KTCYx(500);    //5,000,000 cycles = 1 second
	}
}

void delay_ms(unsigned char x)
{
    char var1;
	for(var1=0;var1<x;var1++)
	{
        Delay1KTCYx(5);    //5,000 cycles = 1 us
	}
}

void delay_us(unsigned char x)
{
    char var1;
	for(var1=0;var1<x;var1++)
	{
        Delay1TCY();    //5 cycle = 1 us
        Delay1TCY();
        Delay1TCY();
        Delay1TCY();
        Delay1TCY();
	}
}
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
////            I2C FUNCTIONS
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
void i2c_clock(void)
{
    SCL = 1;
    delay_us(5);
    SCL = 0;
}

void i2c_start(void){
    SDA_TRIS=0;   //SDA Output
    SCL=0;        //Clock Low
//Start - 5us
    SDA=1;        //SDA High
    SCL=1;        //Clock high
    delay_us(4);
    SDA=0;        //SDA Low
    delay_us(1);
    SCL=0;        //Clock Low
}

void i2c_byte(char addr){
    char bl;
    for(bl=0;bl<8;bl++){

        if((addr & 0x80) != 0)
            SDA = 1;
        else
            SDA = 0;

    i2c_clock();
    addr=addr<<1;
    }
}

void i2c_ack(void){
    SDA_TRIS = 1;   //SDA Input
    i2c_clock();
    delay_us(5);
    //while(SDA);
    SDA_TRIS = 0;
}

char i2c_input(void){
    char temp;
    char i;

    SDA_TRIS = 1;

    temp=0;  
    i = 0;           
    for(i=0;i<8;i++){  
        temp=temp<<1;   

        if(SDA_PORT) 
            temp|=1;

        i2c_clock();
    }

    SDA_TRIS = 0;
    return temp;
}

void i2c_stop(void){
    SDA = 0;
    SCL = 1;
    delay_us(3);
    SDA = 1;
    SCL = 0; 
}
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
////            RTC FUNCTIONS
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
char rtc_write(char offset, char data){

    char temp;
    i2c_start();                //Start
    i2c_byte(slave_w);          //Slave Byte
    i2c_ack();                  //ACK
    i2c_byte(offset);           //Address Offset
    i2c_ack();                  //ACK
    i2c_byte(data);          //Slave Byte    
    i2c_ack();                  //ACK
    i2c_stop;                    //Stop
    return temp;
}
char rtc_read(char offset){

    char temp;
    i2c_start();                //Start
    i2c_byte(slave_w);          //Slave Byte
    i2c_ack();                  //ACK
    i2c_byte(offset);           //Address Offset
    i2c_ack();                  //ACK
    i2c_start();                //Start
    i2c_byte(slave_r);          //Slave Byte    
    i2c_ack();                  //ACK
    temp = i2c_input();         //Get Data
    i2c_ack();                  //ACK
    i2c_stop;                    //Stop
    return temp;
}
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
////            TIME FUNCTIONS
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////

void set_time(void){

    lcd_clr_line(0);
    delay_ms(100);

    lcd_clr_line(1);
    delay_ms(100);
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
    lcd_cmd(Line1);                         //Set to Line 1
    delay_ms(100);

    lcd_string(stringA);                     //Send our string.
    delay_ms(100);

    lcd_clr_line(1);
    delay_ms(50);

    lcd_cmd(Line2);                         //Set to Line 2
    delay_ms(50);

    lcd_string(s_time);                     //Send our string.
    delay_ms(60);  

    while(!set_btn){
        delay_ms(50);
        if(up_btn)
            get_buttons(1);
    }
///////////////////////////////////////////////////////////
    lcd_clr_line(0);
    delay_ms(100);

    lcd_clr_line(1);
    delay_ms(100);
///////////////////////////////////////////////////////////
    lcd_cmd(Line1);                         //Set to Line 1
    delay_ms(100);

    lcd_string(stringB);                     //Send our string.
    delay_ms(100);

    lcd_clr_line(1);
    delay_ms(50);

    lcd_cmd(Line2);                         //Set to Line 2
    delay_ms(50);

    lcd_string(s_time);                     //Send our string.
    delay_ms(60); 

    while(!set_btn){
        delay_ms(50);

        if(up_btn){
            get_buttons(0);
        }    
    }
}

void get_buttons(char hm){
if (hm == 1){
          
    if(s_time[0] == 0x31){
        if(s_time[1] < 0x32){
             s_time[1]++;
        } else {
             s_time[1] = 0x31;
             s_time[0] = 0x30;
        }
    } else {
        s_time[1]++;
        if(s_time[1] > 0x39){
            s_time[1] = 0x30;
            s_time[0]++;
        }
    }


} else {

   s_time[4]++;
           
    if(s_time[4] > 0x39){
        s_time[4] = 0x30;

        if(s_time[3] == 0x35)
            s_time[3] = 0x30;
        else
            s_time[3]++;

    }
}

    lcd_clr_line(1);
    delay_ms(50);

    lcd_cmd(Line2);                         //Set to Line 1
    delay_ms(50);

    lcd_string(s_time);                     //Send our string.
    delay_ms(60);  
        

}
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
////            LCD FUNCTIONS
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
void lcd_clr_line(char line)
{
//This is our clear line command.
    char tline;                             //The line to clear variable
    char x;                                 //loop variable

    if(line==0)                             //set the variable value based on line
        tline=0x80;                         // 0 = Line 1
    else
        tline=0xA8;                         // 1 = Line 2

    lcd_cmd(tline);                         // Send command to jump to beggining of line (1/2)
    delay_ms(1);

    for(x=0;x<40;x++){                      // Loop through all 40 chars of line (even tho 16 are viewable)
        lcd_char(0x20);                     // Send Blank Character
        delay_us(500);                  
    }

    lcd_cmd(tline);                         // Go back to beggining of line
    delay_ms(1);
}


void lcd_init(void)
{                                       //This is our lcd initialization function
    delay_ms(20);                       // Wait at least 16 mS after powerup

	lcd_nybble(0x03,0);                 // send 0x03 cmd 3 times to initialize
	delay_us(160);

	e_togg();                       // Since 0x03 nybble is on the port already
	delay_us(160);                      // we just toggle 2 more times

	e_togg();
	delay_us(160);

	lcd_nybble(0x02,0);                 //Enable 4 bit mode
	delay_us(160);

	lcd_cmd(0x28);			    //set 4-bit mode and 2 lines @ 5x7
	delay_us(160);

	lcd_cmd(0x10);			    //cursor move & shift left
	delay_us(160);

	lcd_cmd(0x06);			    //entry mode = increment
	delay_us(160);

	lcd_cmd(0x0d);			    //display on - cursor blink on
	delay_us(160);

	lcd_cmd(0x01);			    //clear display
	delay_us(160);

    delay_ms(5);
}

void e_togg(void){
    lcd_e = 1;
    lcd_e = 0;
}

void lcd_cmd(unsigned char letter)
{
//This is our Command Function
//The RS is set to 0 to signify this is a command
	unsigned char temp;             //Our temp Variable

	temp=letter;                    //move letter to temp
	temp=temp>>4;                   //shift temp to right by 4
	lcd_nybble(temp,0);             //send the 4 out

	temp=letter;                    //move letter to temp
	temp=temp&0x0f;                 //and out first 4
	lcd_nybble(temp,0);             //send out last 4
}

void lcd_char(unsigned char letter)
{
//This is the same as the lcd_cmd function except
//that is sets RS to 1 telling the lcd this is characters
	unsigned char temp;

	temp=letter;
	temp=temp>>4;
	lcd_nybble(temp,1);

	temp=letter;
	temp=temp&0x0f;
	lcd_nybble(temp,1);
}

void lcd_string(char *senpoint)
{
	while(*senpoint != '\0')            //While we havent seen a \0 (esc) go on
	{
	    lcd_char(*senpoint);            //send 1st char to our char function
	    senpoint++;                     //send next
	}
}
void lcd_nybble(unsigned char nyb,char rs)
{
	char i;
        char x;

        lcd_rs = rs;                    //Set RS Pin (defined in header file)

	for(i=0;i<4;i++){		//Loop through nybble

        if((nyb & 0x08) != 0)           //AND the nybble to 8
	    x=1;                        //if the AND == 1 set x
	else
 	    x=0;                        //if the AND == 0 clear x

        if(i==0)                    //select RA3:RA0 and set/clear pins
            lcd_DB7=x;

        if(i==1)
            lcd_DB6=x;

        if(i==2)
            lcd_DB5=x;

        if(i==3)
            lcd_DB4=x;


        nyb=nyb<<1;                     //shift nybble to the left by 1 (4 times total)
	}

	e_togg();                   //toggle E pin (defined in header file)
}
 
Last edited:
ok found a mojor problem (well for me it is)

My Line:
tmp2 = ((s_time[0]<<4) | s_time[1]); // For setting Hour

How can i add to this line to set the 7:5 bits without changing the others?

The problem is it sets the clock for 24 Hour. I tried :

& 0b00011111;
(and)
| 0b01000000;

This produces a weird result. Lets say i set time to 12:01 it will change it to 62:01 or something like that.

Any thoughts?

Here is the address map.
ds1337d-jpg.22334
 

Attachments

  • ds1337d.jpg
    ds1337d.jpg
    31.8 KB · Views: 193
ok found a mojor problem (well for me it is)

My Line:
tmp2 = ((s_time[0]<<4) | s_time[1]); // For setting Hour

How can i add to this line to set the 7:5 bits without changing the others?

The problem is it sets the clock for 24 Hour. I tried :

& 0b00011111;
(and)
| 0b01000000;

This produces a weird result. Lets say i set time to 12:01 it will change it to 62:01 or something like that.

Any thoughts?

Here is the address map.
ds1337d-jpg.22334

hi atom.
If I am reading correctly you are AND'ing bit6. 24/12 set
Shouldnt you OR it to set B6 in the hours byte.??

EDIT:
hrs = 12: 0001,0010
OR 12hr clock
bit 0100,0000

= 0101,0010 === 52h
 
Last edited:
I dont know much on "&" , "|" but heh
I tried both of them and no good result.

My Quick Fix:
Code:
        hours = rtc_read(0x02);

        if(hours == 0x13){
            hours = 0x01;
            rtc_write(0x02,hours);
        }
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top