EmbeddedRelated.com
The 2024 Embedded Online Conference

Interfacing MAX6952

April 15, 2013 Coded in C for the Microchip PIC16
#define max_sdi PIN_C5
#define max_sdo PIN_C4
#define max_clk PIN_C3
#define max_cs  PIN_C2

const int8 user_font[120]= {0x77,0x6B,0x5D,0x6B,0X77,
                            0x1C,0x22,0x7F,0x22,0x1C,
                            0x77,0x6B,0x5D,0x6B,0X77,
                            0x1C,0x22,0x7F,0x22,0x1C,
                            0x77,0x6B,0x5D,0x6B,0X77,
                            0x1C,0x22,0x7F,0x22,0x1C,
                            0x77,0x6B,0x5D,0x6B,0X77,
                            0x1C,0x22,0x7F,0x22,0x1C,
                            0x77,0x6B,0x5D,0x6B,0X77,
                            0x1C,0x22,0x7F,0x22,0x1C,
                            0x77,0x6B,0x5D,0x6B,0X77,
                            0x1C,0x22,0x7F,0x22,0x1C,
                            0x77,0x6B,0x5D,0x6B,0X77,
                            0x1C,0x22,0x7F,0x22,0x1C,
                            0x77,0x6B,0x5D,0x6B,0X77,
                            0x1C,0x22,0x7F,0x22,0x1C,
                            0x77,0x6B,0x5D,0x6B,0X77,
                            0x1C,0x22,0x7F,0x22,0x1C,
                            0x77,0x6B,0x5D,0x6B,0X77,
                            0x1C,0x22,0x7F,0x22,0x1C,
                            0x77,0x6B,0x5D,0x6B,0X77,
                            0x1C,0x22,0x7F,0x22,0x1C,
                            0x77,0x6B,0x5D,0x6B,0X77,
                            0x1C,0x22,0x7F,0x22,0x1C};
                                                        

#define config_addr 0x04
#define font_addr   0x05
#define test_addr   0x07
#define plane01_addr     0x20
#define plane02_addr     0x21
#define plane03_addr     0x22
#define plane04_addr     0x23
#define plane11_addr     0x40
#define plane12_addr     0x41
#define plane13_addr     0x42
#define plane14_addr     0x43

int8 config_byte;

void write_to_6952(int8 cmd,int8 data)
{
    int8 i;
    int16 ser_data;
    ser_data=make16(cmd,data);
    //shift_right(&ser_data,2,0);
    output_low(max_clk);
    output_low(max_cs);
    for(i=1;i<=16;++i)
    {
        output_bit(max_sdi,shift_left(&ser_data,2,0));
        output_high(max_clk);
        delay_us(10); 
       // if(i<16)       
            output_low(max_clk);
        //delay_us(6); 
    }
    output_high(max_cs);
    output_low(max_clk);
}   

void write_user_font()
{
    int8 j;
    write_to_6952(font_addr,0x80);
    for(j=0;j<120;j++)
    {
        write_to_6952(font_addr,user_font[j]);
    }    
}    
/*******************************************************************
if state=1,normal operation
if state=0,shutdown
if wrt=1,write to 6952,otherwise update the config_byte register
*******************************************************************/
void shutdown(int1 state, int1 wrt)
{
    if(state)
        config_byte |= 0x01;
    else
        config_byte &= 0xFE;
    if(wrt)
        write_to_6952(config_addr,config_byte);
}
/*******************************************************************
if state=1,enable blinking
if state=0,disable blinking
if wrt=1,write to 6952,otherwise update the config_byte register
*******************************************************************/
void blink_enable(int1 state,int1 wrt )
{
    if(state)
       config_byte |= 8;
    else
       config_byte &= 0xF7;
    if( wrt )
        write_to_6952(config_addr,config_byte);
}

/*************************************************************************
if state=1,put the display in test mode
if state=0,normal mode
Does not affect plane data - original display is restored when set 0.
**************************************************************************/
void display_test(int1 state )
{
     if(state)
        write_to_6952(test_addr,1);
     else
        write_to_6952(test_addr,0);
}

Interfacing ADS7807

April 10, 2013 Coded in C for the Microchip PIC16
#define sclk  PIN_D3
#define sdata PIN_D4
#define rc   PIN_D5
#define busy  PIN_D6
#define cs    PIN_C5

void init_ads7807()
{
    output_low(sclk);
    output_high(rc);
    delay_us(2);
    output_high(cs);
}

int32 read_ads7807()
{
BYTE i;
int32 adc_result=0;

while(!input(busy));
output_low(rc);
delay_cycles(1);
output_low(cs);
delay_us(1);
output_high(cs);
delay_cycles(1);
output_high(rc);
while(!input(busy));
output_low(cs);
    for(i=1;i<=16;++i)
    {
        output_high(sclk);
        shift_left(&adc_result,4,input(sdata));
        output_low(sclk);
    }
output_high(cs);
adc_result*=7629;
return adc_result/10000;
}

PGA117 driver

April 9, 2013 Coded in C for the TI MSP430
#define READ 0x6A00
#define WRITE 0x2A00
#define NOP WRITE 0x0000
#define SDN_DIS 0xE100
#define SDN_EN 0xE1F1

#define GAIN_1		0
#define GAIN_2		1
#define GAIN_4		2
#define GAIN_8		3
#define GAIN_16		4
#define GAIN_32		5
#define GAIN_64		6
#define GAIN_128	7

#define CS BIT0
#define DI BIT1
#define DO BIT2

void write_pga(unsigned int value);
void set_ch_gain(unsigned int ch,unsigned int gain);
void config_spi();

void config_spi()
{
	P1DIR |= 0x01;                            // P1.0 output
	P3SEL |= 0x0C;                            // P3.2,3 USCI_B0 option select
	P3DIR |= 0x01;                            // P3.0 output direction
	UCB0CTL0 |= UCMSB + UCMST + UCSYNC;       // 3-pin, 8-bit SPI mstr, MSB 1st
	UCB0CTL1 |= UCSSEL_2;                     // SMCLK
	UCB0BR0 = 0x02;
	UCB0BR1 = 0;
	UCB0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
}

void write_spi(char data)
{
	UCB0TXBUF = data;                  // Byte to SPI TXBUF
	while (!(IFG2 & UCB0TXIFG));       // USCI_A0 TX buffer ready?
}

void write_pga(unsigned int value)
{
	P3OUT &= ~CS;
	write_spi(value>>8);
	write_spi(value);
	P3OUT |= CS;
}

void set_ch_gain(unsigned int ch,unsigned int gain)
{
	unsigned int command;
	command = gain<<4;
	command += ch;
	command +=WRITE;
	write_pga(command);

}

Very simple software timer framework

April 5, 2013 Coded in C
/*********************************************************************************/
/*                                sample usage                                   */
/*********************************************************************************/
#include <lt_timer.h>

LT_TIMER_DEC(slow_timer)		/* declaration */
LT_TIMER_IMP(slow_timer)		/* implementation */

LT_TIMER_DEC(fast_timer)		/* declaration */
LT_TIMER_IMP(fast_timer)		/* implementation */

int main(void)
{
    fast_timer_init();
    slow_timer_init();

    while(1)
    {
	if (slow_timer_expired(1000))
	{
	    //do something each 1000ms 
	}

	if (fast_timer_expired(10))
	{
	    //do something each 10ms 
        }		
	//...............
        //main program functionality
        //...............	
    }
}

/*********************************************************************************/
/*                           lt_timer definition                                 */
/*********************************************************************************/
#ifndef _LT_TIMER_H
#define _LT_TIMER_H

#include <stdint.h>

/* these definitions can vary on different platforms */
typedef unsigned int lt_ticks_t;
typedef int lt_tidiff_t;
typedef unsigned long lt_mstime_t;
typedef signed long lt_msdiff_t;

static lt_ticks_t last_ticks;
static lt_mstime_t actual_msec; 

/* it is expected increment "sys_timer_ticks" variable in some timer interrupt */
/* alternatively some function which return ticks can be provided */
#define lt_get_ticks()      (sys_timer_ticks)		
										
/* in ms (SYS_TIMER_HZ must be provided by user)*/									
#define lt_get_msbase()     (1000/SYS_TIMER_HZ)		

static inline void
lt_mstime_update()
{
  lt_ticks_t act_ticks;
  lt_mstime_t msec_diff;

  act_ticks=lt_get_ticks();
  msec_diff=((lt_tidiff_t)(act_ticks-last_ticks))*lt_get_msbase();
  last_ticks=act_ticks;

  actual_msec+=msec_diff;
}

#define LT_TIMER_DEC(cust_prefix) \
\
extern lt_mstime_t cust_prefix##_last_expired; \
static inline void \
cust_prefix##_init() \
{\
  lt_mstime_update();\
  cust_prefix##_last_expired=actual_msec;\
}\
static inline int \
cust_prefix##_expired(lt_mstime_t expiration) \
{\
  lt_mstime_update();\
  \
  if ((lt_msdiff_t)(actual_msec-cust_prefix##_last_expired)>=expiration) {\
    cust_prefix##_last_expired=actual_msec;\
    return 1;\
  }\
  \
  return 0;\
}

#define LT_TIMER_IMP(cust_prefix) \
\
lt_mstime_t cust_prefix##_last_expired; \

#endif /* _LT_TIMER_H */

General library for debouncing (filtering) of digital inputs

April 3, 2013 Coded in C
/**************************************************************************************/
/*                            sample usage of the library                             */
/**************************************************************************************/

//Remark: sys_timer_ticks should be provided for timing by the user.

/* Simplest example with undefined CONFIG_DEBOUNCE_WITH_HANDLE and CONFIG_DEBOUNCE_SEPARATE_TIMES */

#include <debounce.h>

#define INPUTS_NUM		12
nl_debouce_time_t inp_times[ INPUTS_NUM ];
nl_debouce_time_t filt_time = 10;   //same value will be used for t_on and t_off

int main(void)
{
    nl_inp_t inp_state, filtered_inp_state;

    debounce_init( inp_times, INPUTS_NUM, &filt_time, &filt_time, 
            (nl_ticks_t*)&sys_timer_ticks );

    while(1)
    {
        //user defined function, which return actual state of all inputs as bit array
        inp_state = get_input_state();

        debounce_proc(&inp_state, &filtered_inp_state);
        //do something with filtered_inp_state 

        //...............
        //main program functionality 
        //...............
    }
}

/* More complex example with defined CONFIG_DEBOUNCE_WITH_HANDLE and CONFIG_DEBOUNCE_SEPARATE_TIMES */
#include <debounce.h>

#define INPUTS_NUM		5
struct debounce_state_s inp_dbnc_s;
nl_debouce_time_t inp_times[ INPUTS_NUM ];

nl_debouce_time_t t_on[ INPUTS_NUM ] = {10,10,20,20,50};   
nl_debouce_time_t t_off[ INPUTS_NUM ] = {5,5,10,10,50};   

int main(void)
{
    nl_inp_t inp_state, filtered_inp_state;

    debounce_init( &inp_dbnc_s, inp_times, INPUTS_NUM, 
        t_on, t_off, (nl_ticks_t*)&sys_timer_ticks );

    while(1)
    {
        //user defined function, which return actual state of all inputs as bit array
        inp_state = get_input_state();

        debounce_proc(&inp_dbnc_s, &inp_state, &filtered_inp_state);
        //do something with filtered_inp_state 

        //...............
        //main program functionality 
        //...............
    }
}

/**************************************************************************************/
/*                     debounce library header file "debounce.h"                      */
/**************************************************************************************/
#ifndef _DEBOUNCE_H_
#define _DEBOUNCE_H_
    
#include <stdint.h>

/* because library is multiplatform, following types are defined in separate file */
#include "nlib_types.h"
/* examaple of types definition in "nlib_types.h" */
//typedef   uint32_t    nl_ticks_t;
//typedef   int16_t nl_debouce_time_t;  //so maximum filter time is 32767ms (considering period of ticks 1ms)
//typedef   uint32_t nl_inp_t;  //up to 32 inputs can be handled

/* in general case following macros should be provided in this header file, or can be defined directly */
#include <debounce_config.h>
//#define CONFIG_DEBOUNCE_WITH_HANDLE
//#define CONFIG_DEBOUNCE_SEPARATE_TIMES
    
#ifdef CONFIG_DEBOUNCE_WITH_HANDLE
    #define DEBOUNCE_STRUCT_PAR  struct debounce_state_s * debounce_state,
#else
    #define DEBOUNCE_STRUCT_PAR
#endif

typedef struct debounce_state_s
{
    const nl_ticks_t* ticks; //pointer to timing variable (is incremented e.g. each 1ms)
    nl_ticks_t old_ticks;
    uint_fast8_t inp_num; //number of inputs
    const nl_debouce_time_t *debounce_on_time,*debounce_off_time; //tables with desired filter times
    nl_debouce_time_t* inp_times;   //actual time ON/OFF - non-negative values = ON, negative = OFF
}
debounce_state_t;

void debounce_init(DEBOUNCE_STRUCT_PAR nl_debouce_time_t* inp_tim, uint_fast8_t num, const nl_debouce_time_t *dton,const nl_debouce_time_t *dtoff, const nl_ticks_t* ticks);
uint_fast8_t debounce_proc(DEBOUNCE_STRUCT_PAR const nl_inp_t* act_inp_state, nl_inp_t* debounced_inp_state);

#endif /*_DEBOUNCE_H_*/

/**************************************************************************************/
/*                     debounce library source file "debounce.c"                      */
/**************************************************************************************/

#include "debounce.h"
#include <string.h>

//allow using multiple instances
#ifndef CONFIG_DEBOUNCE_WITH_HANDLE
    struct debounce_state_s _debounce_state_;
    struct debounce_state_s * debounce_state = &_debounce_state_;
#endif

/* allow different times for each input */
#ifndef CONFIG_DEBOUNCE_SEPARATE_TIMES
    #define _debounce_times_idx_ 0
#else
    #define _debounce_times_idx_ i
#endif

//maco trick to find maximum value of given signed integer type "http://www.fefe.de/intof.html"
#define __HALF_MAX_SIGNED(type) ((type)1 << (sizeof(type)*8-2))
#define __MAX_SIGNED(type) (__HALF_MAX_SIGNED(type) - 1 + __HALF_MAX_SIGNED(type))

/*
Init function of the library
	
  DEBOUNCE_STRUCT_PAR - depending on "CONFIG_DEBOUNCE_WITH_HANDLE": nothing, or pointer to handle
  inp_tim - array of variables for storing of state for each input (number of elements must be the same as number of inputs!)
  num - number of inputs
  dton - depending on "CONFIG_DEBOUNCE_SEPARATE_TIMES": pointer to sigle value (minimal ON time), or array of times
  dtoff - depending on "CONFIG_DEBOUNCE_SEPARATE_TIMES": pointer to sigle value (minimal OFF time), or array of times
  ticks - pointer to variable, which is periodicaly incremented
*/
void debounce_init(DEBOUNCE_STRUCT_PAR nl_debouce_time_t* inp_tim, uint_fast8_t num, const nl_debouce_time_t *dton, const nl_debouce_time_t *dtoff ,const nl_ticks_t* ticks)
{
    debounce_state-> inp_times=inp_tim;
    debounce_state-> inp_num=num;
    debounce_state-> debounce_on_time=dton;
    debounce_state-> debounce_off_time=dtoff;
    debounce_state-> ticks=ticks;
    debounce_state-> old_ticks=*ticks;
    memset(inp_tim,0,sizeof(*inp_tim)*num);
    inp_tim[0]=__MAX_SIGNED(nl_debouce_time_t);  //this is used later to evaluate first iteration after start
}

/*
This is core function of the library
	
  DEBOUNCE_STRUCT_PAR - depending on "CONFIG_DEBOUNCE_WITH_HANDLE": nothing, or pointer to handle
  act_inp_state - pointer to variable with actual state of all inputs (1 bit for each input)
  debounced_inp_state - resulting state after filtering
  return - 0=no change, 1=some input(s) are changed 
*/
uint_fast8_t debounce_proc(DEBOUNCE_STRUCT_PAR const nl_inp_t* act_inp_state, nl_inp_t* debounced_inp_state)
{
    uint_fast8_t i,change=0;
    nl_inp_t mask=1;
    nl_ticks_t tic_diff;

    tic_diff=(nl_ticks_t) (*(debounce_state-> ticks) - debounce_state-> old_ticks);
    debounce_state-> old_ticks = *(debounce_state-> ticks);

    if ((debounce_state-> inp_times)[0] == __MAX_SIGNED(nl_debouce_time_t)) //evaluate, if it is a first iteration
    {
        *debounced_inp_state=*act_inp_state;
        for(i=0; i<debounce_state-> inp_num ;i++)
            (debounce_state-> inp_times)[i]=0;
        return 0;
    }

    for(i=0; i<debounce_state-> inp_num ;i++)
    {
        if ( *act_inp_state & mask) //actual state is ON
        {
            if ((debounce_state-> inp_times)[i] >= 0) //and last state was ON
            {
                if (((debounce_state-> inp_times)[i] + (nl_debouce_time_t) tic_diff) < debounce_state-> debounce_on_time[_debounce_times_idx_])
                {
                    (debounce_state-> inp_times)[i] += (nl_debouce_time_t) tic_diff; //filter time not elapsed
                }
                else
                {   //filter time elapsed
                    if (!( *debounced_inp_state & mask))
                    {
                        *debounced_inp_state |= mask;
                        change=1;
                    }
                }
            }
            else (debounce_state-> inp_times)[i] = 0;
        }
        else    //actual state is OFF
        {
            if (debounce_state-> inp_times[i] < 0) //and last state was OFF
            {
                if ( (nl_debouce_time_t)(((debounce_state-> inp_times)[i] - (nl_debouce_time_t) tic_diff)) >= (-1*debounce_state-> debounce_off_time[_debounce_times_idx_]))
                {
                    (debounce_state-> inp_times)[i] -= (nl_debouce_time_t) tic_diff; //filter time not elapsed
                }
                else
                {   //filter time elapsed
                    if ( *debounced_inp_state & mask)
                    {
                        *debounced_inp_state &= ~mask;
                        change=1;
                    }
                }
            }
            else (debounce_state-> inp_times)[i] = -1;
        }
        mask=(nl_inp_t) mask<<1;

    }
    return change;
}

Implementation of a basic task scheduler

April 3, 2013 Coded in C
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
 
#define MAX_PROCESSES 32 /* the maximal number of processes in the system */
#define MAX_NAME_LEN 32
 
/* Process control block -
* holding all process relevant informations
*/
struct pcb{
	int pid; /* ID of the proces */
	int prio; /* process priority */
	int attached; /* 1 if attached to processlist, else 0 */
	int *function; /* pointer to the process function */
	char name[MAX_NAME_LEN]; /* Name of the process */
};
 
static struct pcb processlist[MAX_PROCESSES];
int process0();
int process1();
 
int process_attach(char *name, int prio, void *function)
{
	int i = 0;
	int ret = -1;
	printf("[dbg] process_attach\n");
	while(i < MAX_PROCESSES) {
		if(strlen(name) > MAX_NAME_LEN) {
			printf("[err] wrong stringlen\n");
			return ret;
		}
		if(processlist[i].attached != 1) {
			printf("attach process at %d\n", i);
			processlist[i].pid = i;
			strcpy(processlist[i].name, name);
			processlist[i].prio = prio;
			processlist[i].function = function;
			processlist[i].attached = 1;
			ret = 0;
			break;
		}
		printf("\n");
		i++;
	}
	return ret;
 
}
 
int process_detach(int pid)
{
	processlist[pid].attached = 0;
	return 0;
}
 
/*
* basic implementation of a RR scheduler
*/
int scheduler()
{
	int i = 0;
	void (*p)(void);
	while(1) {
		for(i = 0; i < MAX_PROCESSES; i++) {
			if(processlist[i].attached == 1) {
			p = (void *)processlist[i].function;
			(*p)();
			}
		}
	}
	return 0;
}
 
/*** Testdriver ***/
int process0()
{
	printf("0\n");
	return 0;
}
 
int process1()
{
	printf("1\n");
	return 0;
}
 
int main()
{
	/*
	* test run here
	* */
	printf("basic_scheduler Demo\n");
	process_attach("process0", 100, process0);
	process_attach("process1", 50, process1);
	scheduler();
	return 0;
}

LED Blinker Using a Timer/Counter

Stephen Friederichs April 2, 2013 Coded in C for the ATMega328P
/**@file timer_blinker.c
   @brief A more advanced LED blinker using a timer
   @author Stephen Friederichs
   @date 3/28/13
   @note This code assumes that the LED is active high (pin sources current)   
*/   

/**@def F_CPU
   @brief Clock frequency = 8MHZ - this is set by fuses and registers, not by this define
   @note Always define this before including delay.h!
*/
#define F_CPU 8000000
	
/**@include io.h
   @brief Include for AVR I/O register definitions
*/
#include <avr/io.h>

/**@include stdint.h
   @brief Include for standard integer definitions (ie, uint8_t, int32_t, etc)
*/
#include <stdint.h>

/**@include delay.h
   @brief Include for delay functions such as _delay_ms() and _delay_us()
*/
#include <util/delay.h>

/* Basic bit manipulation macros - everyone should use these.  Please, steal these! Don't not use them and
 don't rewrite them yourself!
*/
#define SET(x,y) x |= (1 << y)
#define CLEAR(x,y) x &= ~(1<< y)
#define READ(x,y) ((0x00 == ((x & (1<<y))>> y))?0x00:0x01)
#define TOGGLE(x,y) (x ^= (1<<y))

int main(void)
{
	/*Initialization Code*/
	
	/*	ATMega328 Datasheet Table 14-1 Pg 78
		Configure PD7 for use as Heartbeat LED
		Set as Output Low (initially)
	*/
	SET(DDRD,7);	//Direction: output
	CLEAR(PORTD,7);	//State: Lo

	/*	TCCR1A - ATMega328 Datasheet Section 16.11.1 pg 132
		No waveform generation is required on this timer, so set all
		ports to normal operation
	*/	
	TCCR1A = 0x00;
		
	/*	TCCR1C - ATMega328 Datasheet Section 16.11.3 pg 135 
		This register is only used for output compare.  
		There's no output compare in this application so this can be all 0's
	*/
	TCCR1C = 0x00;
		

	/*	TCCR1B
		
		Note: I've disabled the CKDIV8 fuse so that the clock source is 8MHz
	
		ATMega328 Datasheet Section 16.11.2 pg 134 - TCCR1A
		No input capture used - bits 7:6 are 0
		No waveform generation used - bits 4:3 are 0
		Clock source select is bits 2:0 but are not yet set - wait until the 
		main loop is ready to start
		
		As per ATMega328 Datasheet Section 16.9.1 page 123, setting the timer 
		to Normal mode causes the counter to count up until it reaches 0xFFFF
		at which point it will overrun and start back at 0.  To configure this
		timer/counter to produce a period of 500ms we need to start counting 
		at a value that causes it to reach 65535 in 500ms. 
		
		What is that value?

		With a clock prescaler of 256 each count of the timer is roughly
		(1/8MHz)*256 = 32uS
		500ms / 32us /tick = 15625 ticks /500ms
		The counter counts up to 65535, so to determine what value we have to
		start at we subtract 15635 from 65536:
		65536-15625 = 49910
	*/

	#define TIMER1_PERIOD 49910
		
	TCNT1 = TIMER1_PERIOD;

	/*	Flash the LED for a second to show that initialization has successfully 
		occurred
	*/
	SET(PORTD,7);
	_delay_ms(1000);
	CLEAR(PORTD,7);
	
	/*	Start the timer/counter
		ATMega328 Datasheet Section 16.11.2 Pg 135 - TCCR1B
		No Waveform generation: bits 4:3 = 0
		No input capture: bits 7:6 = 0
		Clock select: ClkIO/256 - bits 2:0 = 100b = 0x04
	*/	
	TCCR1B = 0x04;	//This starts the counter/timer
	
	while(1)
	{
		/*	Handle the Heartbeat LED
			When the timer/counter reaches 65535 the 500ms period will have 
			elapsed and TIFR1 bit 1 will be '1'
		*/
		if(READ(TIFR1,0))
		{
			/*	ATMega328 Datasheet Section 16.11.9 pg137
				Setting TIFR1 bit 1 clears the overflow flag 
			*/
			SET(TIFR1,0);	
				
			/*	Toggle the LED to flash it at 1Hz*/ 
			TOGGLE(PORTD,7);
			
			/*	Reload the timer/counter count value to the previous value
				so that the period remains the same
			*/
			TCNT1 = TIMER1_PERIOD;
		}
		
		/*	Now you can do useful work here - no delay loops!*/
	
	}

}

Delay Loop LED Blinker

Stephen Friederichs April 2, 2013 Coded in C for the ATMega328P
/**@file led_blink.c
   @brief The most basic approach to blinking an LED on AVR microcontrollers - specifically the ATMega328P
   @author Stephen Friederichs
   @date 3/28/13
   @note This code assumes that the LED is active high (pin sources current)   
*/   

/**@def F_CPU
   @brief Clock frequency = 8MHZ - this is set by fuses and registers, not by this define
   @note Always define this before including delay.h!
*/
#define F_CPU 8000000
	
/**@include io.h
   @brief Include for AVR I/O register definitions
*/
#include <avr/io.h>

/**@include stdint.h
   @brief Include for standard integer definitions (ie, uint8_t, int32_t, etc)
*/
#include <stdint.h>

/**@include delay.h
   @brief Include for delay functions such as _delay_ms() and _delay_us()
*/
#include <util/delay.h>

/* Basic bit manipulation macros - everyone should use these.  Please, steal these! Don't not use them and
 don't rewrite them yourself!
*/
#define SET(x,y) x |= (1 << y)
#define CLEAR(x,y) x &= ~(1<< y)
#define READ(x,y) ((FALSE == ((x & (1<<y))>> y))?FALSE:TRUE)
#define TOGGLE(x,y) (x ^= (1<<y))

int main(void)
{
	/*Initialization Code*/
	
	/*	ATMega328 Datasheet Table 14-1 Pg 78
		Configure PD7 for use as Heartbeat LED
		Set as Output Low (initially)
	*/
	SET(DDRD,7);	//Direction: output
	CLEAR(PORTD,7);	//State: Lo

	/*	Flash the LED for a second to show that initialization has successfully 
		occurred
	*/
	SET(PORTD,7);
	_delay_ms(1000);
	CLEAR(PORTD,7);
	
	while(1)
	{
		/*Set PD7 low for 500ms*/
		CLEAR(PORTD,7);
		_delay_ms(500);
		
		/*Then set it high for 500ms*/
		SET(PORTD,7);
		_delay_ms(500);
		
		/*Before repeating the process forever...*/
	
	}

}

SR-87 GPS Module

April 2, 2013 Coded in C for the Microchip PIC16
#use rs232(baud=4800,xmit=PIN_C6,rcv=PIN_C7,bits=8,stop=1,parity=n,stream=GPS,force_sw)

#include<string.h>
#include<stdlib.h>
//char latitude[17],longitude[17],buffer[17];

// Read the lattitude and longitude
void get_position()
{
	int8 rx_count,rx_buffer;
	rx_count=0;
	strcpy(buffer,"GPRMC");
	do
	{
		rx_count=0;
		output_low(PIN_A5);
		while(fgetc(GPS) !='$');
		while((rx_buffer=fgetc(GPS))!=',')
		{
			latitude[rx_count]=rx_buffer;
			rx_count++;
		}
		latitude[rx_count]='\0';
	}while(strcmp(latitude,buffer));
//*****************************************************************
	while(getc(GPS)!=',');
	while(getc(GPS)!=',');
	rx_count=0;
	do
	{
		rx_buffer=fgetc(GPS);
		latitude[rx_count]=rx_buffer;
		rx_count++;
	}while(rx_buffer!=',');
	latitude[rx_count]=fgetc(GPS);
	rx_count++;
	latitude[rx_count]='\0';
	rx_buffer=fgetc(GPS);
	rx_count=0;
	do
	{
		rx_buffer=fgetc(GPS);
		longitude[rx_count]=rx_buffer;
		rx_count++;
	}while(rx_buffer!=',');
	longitude[rx_count]=fgetc(GPS);
	rx_count++;
	longitude[rx_count]='\0';

}	
//wait untill a valid data
void get_fix()
{
   int8 rx_count,rx_buffer;
   rx_count=0;
   strcpy(buffer,"GPRMC");
   do
   {
      do
      {
         rx_count=0;
         while(fgetc(GPS) !='$');
         while((rx_buffer=fgetc(GPS))!=',')
         {
            latitude[rx_count]=rx_buffer;
            rx_count++;
         }
         latitude[rx_count]='\0';
      }while(strcmp(latitude,buffer));
      
      while(fgetc(GPS) !=',');
      rx_buffer=fgetc(GPS);
   }while(rx_buffer !='A');   
   

}

A simple software timer system

March 31, 20132 comments Coded in C
/**
 * @file
 * Software timer facility.
 *
 * This module implements an unlimited number of 8-bit down-counting 10ms and 
 * 100ms timers.  Timers are actually held in various places by the application
 * code and are registered with this module for service from the system's 
 * timekeeping interrupt.
 *
 * A down-counting timer starts out set to a time interval and is
 * automatically decremented via the system's periodic interrupt.  Check for a
 * zero value to know when the timer has expired:
 *
 * <pre>uint8_t my_timer = 10;
 * timer_register_100ms(&my_timer);
 *
 * for (;;)
 * {
 *   if (my_timer == 0)
 *   {
 *     do_something();
 *     my_timer = 10;
 *   }
 * }</pre>
 *
 * Down-counting timers are restricted to 8 bits so that they can be
 * atomically manipulated outside interrupt code on 8-bit architectures
 * without resorting to disable interrupts.
 *
 * @warning All variables used as timers must be declared
 *          <code>volatile</code>, because they are modified from an interrupt
 *          context that may not be understood by the compiler.  GCC in
 *          particular is known to optimize away timer variables that aren't
 *          declared <code>volatile</code>.
 *
 * <h2>Configuration</h2>
 * The number of available 10ms and 100ms timer slots is set using
 * {@link MAX_100MS_TIMERS} and {@link MAX_10MS_TIMERS}.
 */

#include <stdlib.h>    /* for NULL */
#include <stdint.h>    /* uint8_t, etc. */
#include <stdbool.h>   /* bool type, true, false */

#include "timer.h"

/** Maximum number of 100ms timers that can be registered. */
#define MAX_100MS_TIMERS 10

/** Maximum number of 10ms timers that can be registered. */
#define MAX_10MS_TIMERS  10

/** The polling frequency for the 10ms timers is scaled by this factor to
    service the 100ms timers. */
#define PRESCALE_100MS   10

/* ------------------------------------------------------------------------ */

/** 10ms timer array.  These are pointers to the actual timers elsewhere in
    the application code. */
static volatile uint8_t *timers_10ms [MAX_10MS_TIMERS];

/** 100ms timer array.  These are pointers to the actual timers elsewhere in
    the application code. */
static volatile uint8_t *timers_100ms [MAX_100MS_TIMERS];

bool timer_register_10ms (volatile uint8_t *t)
{
  uint8_t k;
  
  for (k = 0; k < MAX_10MS_TIMERS; ++k)
  {
    if (NULL == timers_10ms[k])
    {
      /* Success--found an unused slot */
      timers_10ms[k] = t;
      return false;
    }
  }
  
  /* Failure */
  return true;
}

bool timer_register_100ms (volatile uint8_t *t)
{
  uint8_t k;
  
  for (k = 0; k < MAX_100MS_TIMERS; ++k)
  {
    if (NULL == timers_100ms[k])
    {
      /* Success--found an unused slot */
      timers_100ms[k] = t;
      return false;
    }
  }
  
  /* Failure */
  return true;
}

void timer_poll (void)
{
  static uint8_t prescaler = PRESCALE_100MS;
  volatile uint8_t *t;
  uint8_t k;
  
  /* Service the 10ms timers */
  for (k = 0; k < MAX_10MS_TIMERS; ++k)
  {
    t = timers_10ms[k];
    
    /* First NULL entry marks the end of the registered timers */
    if (t == NULL)
    {
      break;
    }
    
    if (*t > 0)
    {
      -- *t;
    }
  }
  
  /* Now divide the frequency by 10 and service the 100ms timers every 10th
     time through. */
  if (--prescaler == 0)
  {
    prescaler = PRESCALE_100MS;

    for (k = 0; k < MAX_100MS_TIMERS; ++k)
    {
      t = timers_100ms[k];
      
      if (t == NULL)
      {
        break;
      }
      
      if (*t > 0)
      {
        -- *t;
      }
    }
  }
}

/* Header file */
#if !defined(TIMER_H)
#define TIMER_H

/**
 * @file
 */

#include <stdbool.h>
#include <stdlib.h>

/**
 * Registers a 10-millisecond timer for service.
 *
 * @param[in]  t  pointer to the variable used for timing
 *
 * @retval     true   if registration failed
 * @retval     false  if registration succeeded (normal return)
 */
bool timer_register_10ms (volatile uint8_t *t);

/**
 * Registers a 100-millisecond timer for service.
 *
 * @param[in]  t  pointer to the variable used for timing
 *
 * @retval     true   if registration failed
 * @retval     false  if registration succeeded (normal return)
 */
bool timer_register_100ms (volatile uint8_t *t);

/**
 * Maintains all registered timers.
 *
 * This function should be called from a stable 10-millisecond time base,
 * preferably from an interrupt.
 */
void timer_poll (void);

#endif /* TIMER_H */

The 2024 Embedded Online Conference