You have no items in your shopping cart.

Subtotal: 0.00

Introduction

This chapter explains how you can maximize the efficiency of your applications by writing your C source in such a way as to make the compiler generate fast and compact machine code. It gives advice on which command line switches to use with the C compiler to optimize the resulting program, and shows you how to identify and eliminate unused sections of code. It describes how to compile and link C code for deeply embedded applications, using the components of the standalone C runtime system.

Writing Efficient C for the dsPIC

The C compiler can generate very good machine code for if you present it with the right sort of input. In this section we explain:

☞What the C compiler compiles well and why.

☞How to help the C compiler generate efficient machine code.

Some of the rules presented here are quite general; some are quite specific to the dsPIC or the C compiler. It should be clear from context which rules are portable.

When writing C, there are a number of considerations which, if handled intelligently, will result in more compact and efficient dsPIC code:

☞The way functions are written, their size, and the way in which they call each other.

☞The distribution of variables within functions, and their scoping.

This affects the register allocation of variables, and the frequency with which they are spilled to memory:

☞The use of alternatives to the switch () statement

Under certain circumstances, reductions in code size can be achieved by avoiding the use of switch ().

The basic concepts of the programming language C

All examples are presented in this tutorial rely on the programming language C and its application in the C30 compiler for dsPIC. It is thus necessary to introduce some of the concepts, modes of their applications, and their meanings in order to facilitate understanding of the abundant examples contained by the tutorial.

The simplest structures of C are used, so the examples can be understood with no need for an analysis of the programming language.

NOTE: In this chapter no complete C language used by the compiler has been presented, but only some of the methods of declaring types and some of the key words often used in the examples.

The reader is referred to the help-system accompanying the C30 compiler for a detailed study of the possibilities of the C language and its application in programming the microcontrollers of the family dsPIC30F.

The memory of a microcontroller of the family dsPIC30F keeps 16-bit (2-bytes) basic data. All other types of data are derived from these. The compiler also supports 1-byte and 4-bytes data. Both integer and floating point variables are supported. This chapter will present the most frequently used types of data.

The table presents a review of integer variables supported by the dsPIC C30 compiler as shown in below.

Type

Size in bytes

Range

(unsigned) char

1

0 .. 255

signed char

1

- 128 .. 127

(signed) short (int)

1

- 128 .. 127

unsigned short (int)

1

0 .. 255

(signed) int

2

-32768 .. 32767

unsigned (int)

2

0 .. 65535

(signed) long (int)

4

-2147483648 .. 2147483647

unsigned long (int)

4

0 .. 4294967295

 

Example – declaring integer variable:

int i;

long l;

Example – declaration of a floating point variable:

The floating point variables are supported by the type of data float, double and long double, 32 bits wide in the memory and of the range (-1.5 * 1045 .. +3.4 * 1038).

float fnumber;

Example – declaration of arrays:

A set of variables of the same type, if indexed, is represented by an array.

int vector_one[10];

int days[12] = {31,28,31,30,31,30,31,31,30,31,30,31};

As can be noticed from the above examples, the indexes in an array can start from any integer value. If within the square brackets only one value is declared, the array has so many members (10 in the above example).

In that case the index of the first member iz zero!

Example – declaration of type string:

A series of characters is represented by a type of data called string. It, in essence, represents an array of the type char, but sometimes it is useful to be considered as text.

char txt[6] = "mikro";

Example – declaration of pointer:

More difficult to understand, but often used type of data is pointer. It serves for keeping the address in the memory where some essential information is kept.

int *ptra;

Keywords

Key words are the concepts in a programming language having special meanings. The names of the variables must not use this set of words.

Key word ASM

Key word asm denotes the beginning of an instruction block written in the assembler. The compiler supports the assembler instructions. If an exceptional speed of execution of a part of a code is required, and the user possesses the corresponding knowledge of the microcontroller architecture and assembler instructions, then the critical part of the programs could be written in the assembler (user-optimized parts of the code).

Note: The block of assembler instructions has to start by the key word asm { and finish by } !

Example – use of the key word asm:

asm {
  MOVLW 10  // just a test
  MOVLW _myvar
  MOVLW 0   // just a test
  MOVLW _myvar+1

}

When using the key word asm, care has to be taken of the available resources. For this reason the use of this key word is not recommended unless it is necessary. The use of the key word asm is necessary when using the DSP module. In this case there is no alternative if the maximum use of the DSP module is targeted.

Key word ABSOLUTE

Key word absolute is used in cases when it is required that certain variable is saved at a memory cell which is determined in advance. In majority of cases the use of the key word absolute does not make sense. However, its use is sometimes necessary when using the DSP.

Example – the use of the key word absolute:

int coef[10] absolute 0x0900; double series[16] absolute 0x1900;

In the above example array coef is located at address 0x0900 in the memory. It takes 10x2=20 bytes (10 elements, 2 bytes each), i.e. 20 address (10 locations), thus the range of addresses containing the elements of array coef is (0x0900 ... 0x0913). Array series is located at address 0x1900 in the memory. It takes 16x4=64 bytes (16 elements, 4 bytes each), i.e. 64 addresses (32 locations) and the range of addresses containing the elements of array series is (0x1900 ... 0x193F).

Key word ORG

The key word org is used in situations when it is required that certain method (function) is saved at a pre-assigned address in the program memory (the part of the memory where the program is saved). The use of the key word org is necessary when processing the interrupts or traps. The methods (functions) of processing interrupts or traps have to be kept at a precisely specified address.

Example – the use of the key word org:

void ADC1_Int() org 0x2A
{
  int s;
  IFS0.F11 = 0; //clear AD1IF
  s = ADCBUF0; //fetch sample
}

The above example shows the method of instructing the compiler that the given function is saved in the part of the program memory starting from location 0x2A.

Configuration Bits

Prior to the start of programming a microcontroller, it is necessary to set the conditions governing the operation of the microcontroller.

The governing conditions imply the clock defining the speed of execution of instructions, the source of the clock, the protection against the instabilities of the power supply, the protection against the irregular execution of the parts of the program etc.

The configuration of a microcontroller is carried out by the four registers:

Register

Name

Address

FOSC

Oscillator Configuration Register

0xF80000

FWDT

Watchdog Timer Configuration Register

0xF80002

FBORPOR

BOR and POR (Voltage Protection) Configuration Register

0xF80004

FGS

General Code Segment Configuration Register

0xF8000A

 

These registers are in the programming memory in the upper half of the memory. Details concerning the programming memory can be found in Chapter 8 of the book. It is important to know that the locations in the programming memory are 24-bit wide.

Oscillator configuration registers (FOSC)

The oscillator configuration register is used for adjusting the clock of the microcontroller. The clock is of direct influence on the speed of execution of instructions. It is thus essential that the clock is selected correctly. It is also essential to select the oscillator source. The source can be the internal RC oscillator (FRC – internal fast RC oscillator, LPRC – internal low power RC oscillator) or external oscillator (ERC – external RC oscillator, XT – external quartz).

Configuration registers of the watchdog timer (FWDT)

The configuration register of the watchdog timer serves for switching on and off of the watchdog timer and for the adjustment (presetting) of its operation. The present value is a number dividing the internal RC clock to obtain, in this case, the clock of the watchdog timer.

The watchdog timer is independent of the internal clock which governs the execution of instructions.

In this way an operative timer is obtained even if the internal clock fails. The frequency of the RC oscillator for the watchdog timer is 512 kHz. After the initial division by 4 one obtains the 128 kHz which is the basic clock of the watchdog timer.

Voltage protection configuration registers (FBORPOR)

The configuration register of the voltage protection serves for defining the minimum value of the supply voltage, switching on/off the circuit for resetting the microcontroller if the supply voltage falls below the specified value, and for adjustment of the PWM output.

The proper execution of programs requires a good stability of the power supply. The family of microcontroller’s dsPIC30F has the ability of defining a minimum power supply voltage ensuring proper functioning of the device.

If the supply voltage falls below this limit, the internal circuit will reset the microcontroller, wait until the supply voltage returns above the limit, and after the specified power-up delay time activate the microcontroller starting the execution of the program for the beginning.

Program memory protection configuration registers (FGS)

The program memory protection configuration register is used to code protect or write protect the program memory space. It includes all user program memory with the exception of the interrupt vector table space.

If the program memory is code protected, the device program memory cannot be read from the device using in-circuit serial programming or the device programmer. Further code cannot be programmed into the device without first erasing the entire general code segment.

The program memory protection register uses only two configuration bits, the others are unimplemented. The two configuration bits must be programmed as a group.

If the code protect and write protect of the program memory are enabled, a full chip erase must be performed to change the state of either bit.

Interrupts

Interrupts are unexpected events in a sequence of execution of instructions causing an interruption of the normal programming flow. The causes of interrupts can be different. For the family of dsPIC30F microcontrollers, in the transducer or general purpose applications, 41 interrupt sources and 4 types of traps, ranked according to the priority schematic, have been specified.

For each specified interrupt or trap the microcontroller (MCU) has a clearly defined further programme sequence specified by the interrupt vector table (IVT). The IVT contains the initial addresses of interrupt routines for each interrupt source or trap. IVT is located in the programme memory starting at location 0x000004 up to location 0x00007E.

In addition to the interrupt vector table, in the family of dsPIC30F microcontrollers, the alternate interrupt vector table (AIVT) is also specified. The purpose of the AIVT is to enable the realization of alternate interrupt routines. The AIVT is also located in the programme memory starting at location 0x000084 up to location 0x0000FE.

On the basis of the priorities specified by the special function registers, the interrupt controller is responsible for the preparation and preprocessing of interrupts:

IFS0<15:0>, IFS1<15:0>, and IFS2<15:0>are the registers containing all the interrupt request flags. Each source of interrupt has a status bit set by the respective peripherals or external signals. These flags are cleared by the user software.

IEC0<15:0>, IEC1<15:0>, and IEC2<15:0>are the registers containing all the interrupt enable control bits. These control bits are used to individually enable interrupts from the peripherals or external signals.

IPC0<15:0>, IPC1<15:0> … IPC10<7:0>are the registers used to set the interrupt priority level for each of the 41 sources of interrupt.

IPL<3:0> are the bits containing the current CPU priority level. IPL<3> bit is located in the register CORCON and the remaining three bits IPL<2:0>are in the STATUS register (SR) of the microcontroller.

INTCON1<15:0> and INTCON2<15:0> are the registers containing global interrupt control functions. INTCON1 contains the control and status bits for the processor trap sources; INTCON2 controls the external interrupt requests behavior and the use of the alternate vector table by setting the ALTIVT bit (INTCON2<15:0>).

During processor initialization it is necessary to enable interrupts which will be used and assign the corresponding priority levels.

int a;

void IntDet() org 0x0014 //vector INT0

{

LATB--; //port B is decremented

IFS0.F0 = 0; //interrupt flag cleared

}

Timers

Timers are basic peripherals of each microcontroller. Depending upon the model, the dsPIC30F family offers several 16-bit timer modules. Microcontroller dsPIC30F4013 contains 5 timer modules.

Each timer module contains one 16-bit timer/counter consisting of the following registers:

TMR x – 16-bit timer counter register,

PR x – 16-bit period register containing value of the period,

TXCON – 16-bit control register for selecting mode of the timer.

Each timer module also has the associated bits for interrupt control:

Tx IE – interrupt enable control bit,

Tx IF – interrupt flag status bit,

Tx IP<2:0> - three interrupt priority control bits (in the interrupt register IPC x).

Most of the timers in the family of dsPIC30F microcontrollers have the same functional circuitry. Depending of their functional differences, they are classified into three types: A, B, or C. Timers of the types B and C can be combined to form a 32-bit timer.

Type A timer

Type A timer is available on most dsPIC30F devices. Timer1 is a type A timer. A type A timer has the following unique features over other types:

☞It can be operated from the device low power 32 kHz oscillator,

☞It can be operated in an asynchronous mode from an external clock source.

The unique feature of a type A timer is that it can be used for real-time clock (RTC) applications.

Type A timer is a general purpose (GP) 16-bit timer and in the microcontroller dsPIC30F4013 it is denoted as timer1 module.

Timer1 module is a 16-bit timer primarily intended for use as a real time counter, or universal period meter, or event counter in the free-running mode. Timer1 can be configured to operate as:

☞A 16-bit timer,

☞A 16-bit synchronous counter,

☞A 16-bit asynchronous counter.

Also, timer1 has the ability to operate as a gated timer, select a pre scalar, operate during SLEEP or IDLE states of the microcontroller, as well as generate an interrupt request when the value of the register TMR1 equals that of the period register PR1. The condition for generating an interrupt request could be the falling edge of an external gating signal (TGATE).

Control of the operation of the timer1 module is determined by setting bits in the 16-bit configuration special function register (SFR) T1CON.

16-bit timer mode

In the 16-bit timer mode the value of the TMR1 counter is incremented by each instruction cycle until it is equal to the pre-set value of the PR1 register, when the counter is reset to ‘0’ and restarted. At this moment an interrupt request for timer1 module T1IF (in the register IFS0) is generated. Processing of this request depends on the interrupt T1IE enable bit (in the IEC0 register).

Timer module continues to operate during the interrupt routine.

Timer1 module can operate during the IDLE state if the TSIDL bit (T1CON<13>) is reset, but if this bit is set, the counter continues to operate after the processor is waken-up from IDLE state.

Note

Interrupt of timer1 module is generated upon an interrupt request set by timer1 module only if the interrupt is enabled by setting the T1IE bit in the IEC0 register. The interrupt request bit T1IF in the IFS0 register has to be reset by the software after the interrupt is generated.

The following example demonstrates how timer1 module can be used in the 16-bit timer mode.

Example

Switch on and off a LED diode at port D approximately 4 times per second. This example uses timer1 module having clock 256 times slower than the dsPIC clock.

At each 10,000 clocks timer1 module calls interrupt routine Timer1Int and changes the value at port D.

void Timer1Int() org 0x1A

{// Timer1 address in the interrupt vector table

LATD = ~PORTD; // PORTD inversion

IFS0 = IFS0 & 0xFFF7; // Interrupt flag reset

}

void main()

{

TRISD = 0; // PORTD is output

LATD = 0xAAAA; // Set initial value at port D

IPC0 = IPC0 | 0x1000; // Priority level is 1

IEC0 = IEC0 | 0x0008; // Timer1 interrupt enabled

PR1 = 10000; // Interrupt period is 10000 clocks

T1CON = 0x8030; // Timer1 enabled (internal clock divided by 256)

while(1) asm NOP; // Endless loop

}

How does one calculate the period of interrupt requests? Let the internal clock be set to 10MHz. The period is 100ns. Since the clock is divided by 256 (pre-scalar reduces the clock 1:256) to form the timer clock, it follows that the timer clock is 100*256=25600ns i.e. 25.6µs. At each 10000 clocks an interrupt is requested, i.e. at each 256ms or approximately 4 times per second.

T = 10000*25.6µs = 256ms ~ ¼s.

16-bit synchronous counter mode

In the 16-bit synchronous counter mode the counter value TMR1 increments on every rising edge of an external clock source. In this mode the phase of the internal clock is synchronized with the external clock. When the value of the TMR1 counter is equal to the pre-set value of the PR1 register, the counter TMR1 is reset and starts counting from ‘0’. At this moment an interrupt request for timer1 module T1IF is generated. Processing of this request depends on the interrupt T1IE enable bit.

Timer module continues to operate during the interrupt routine.

The purpose of the timer1 module is to allow measurement of the periods of very fast clock signals, e.g. auto detection of the speed of communication of the universal serial interface UART.

The timer1 module could operate in this mode during IDLE state if bit TSIDL (T1CON<13>) is reset; if this bit is set, the counter continues operation after the processor is waken-up from IDLE state.

The following example demonstrates how timer1 module can be used in the synchronous counter mode.

Example

Count every tenth pulse and increment the value at port D. In this example timer1 is used for counting external clock pulses at pin T1CK. After ten pulses interrupt Timer1Int occurs and the value at port D is incremented.

pin-t1ck
void Timer1Int() org 0x1A

{ // Timer1 address in the interrupt vector table

LATD = ~PORTD; // Value at PORTD is incremented

IFS0 = IFS0 & 0xFFF7; // Interrupt request is reset

}

void main(){

TRISD = 0; // PORTD is output

TRISC = 0x4000; // PORT=1 T1CK input pin

LATD = 0; // Set initial value at port D

IPC0 = IPC0 | 0x1000; // Priority level is 1

IEC0 = IEC0 | 0x0008; // Timer1 interrupt enabled

PR1 = 10; // Interrupt period is 10 clocks

T1CON = 0x8006; // Timer1 is synchronous counter of external pulses

while(1) asm NOP; // Endless loop

}

16-bit asynchronous counter mode

In the 16-bit asynchronous counter mode the counter value TMR1 increments on every rising edge of an external clock source, but the phase of the internal clock is not synchronized with the external clock.

When the value of the TMR1 counter is equal to the pre-set value of the PR1 register, the counter TMR1 is reset and starts counting from ‘0’. At this moment an interrupt request for timer1 module T1IF (in the register IFS0) is generated. Processing of this request depends on the interrupt T1IE enable bit (in the IEC0 register).

Timer module continues to operate during the interrupt routine.

The timer1 module could operate in this mode during IDLE state if bit TSIDL (T1CON<13>) is reset; if this bit is set, the counter continues operation after the processor is waken-up from IDLE state.

Example

Count each 800th pulse and increment the value at port D. In this example timer1 is used to count each 8th pulse of an external clock at the external pin T1CK. After 100 pulses the interrupt routine Timer1Int is called and the value at port D is incremented.

pin-t1ck
void Timer1Int() org 0x1A

{ // Timer1 address in the interrupt vector table

LATD++; // Value at PORTD is incremented

IFS0 = IFS0 & 0xFFF7; // Interrupt request is reset

}

 

void main()

{

TRISD = 0; // PORTD is output

TRISC = 0x4000; // PORT=1 T1CK is input pin

LATD = 0; // Set initial value at port D

IPC0 = IPC0 | 0x1000; // Priority level is 1

IEC0 = IEC0 | 0x0008; // Timer1 interrupt enabled

PR1 = 100; // Interrupt period is 100 clocks

T1CON = 0x8012; // Timer1 is synchronous counter of external pulses

while (1) asm NOP; // Endless loop

}

The timer1 module could operate in this mode during IDLE state if bit TSIDL (T1CON<13>) is reset; if this bit is set, the counter continues operation after the processor is waken-up from IDLE state.

Example

Use timer1 in the gated time accumulation mode. The enable GATE signal is applied to the pin T1CK. Measure the width of the signal and display the result at port D.

pin-t1ck
void Timer1Int() org 0x1A

{// Timer1 address in the interrupt vector table

LATD = TMR1; // Pulse duration is displayed at port D

IFS0 = IFS0 & 0xFFF7; // Interrupt request is processed

}

main()

{

TRISD = 0; // PORTD is output

TRISC = 0x4000; // PORT=1 T1CK is input pin

LATD = 0; // Set initial value at port D

IPC0 = IPC0 | 0x1000; // Priority level is 1

IEC0 = IEC0 | 0x0008; // Timer1 interrupt enabled

PR1 = 0xFFFF; // Period is maximum

T1CON = 0x8040; // Timer1 is enabled, internal clock until T1CK=1

while (1) asm NOP; // Endless loop

}

Type B timer

Type B timer is a 16-bit timer present in most devices of the dsPIC30F family of microcontrollers. It is denoted as the timer2 module and timer4 module like in dsPIC30F4013 microcontroller. Type B timer has the following specific features:

☞a type B timer can be concatenated with a type C timer to form a 32-bit timer,

☞The clock synchronization for a type B timer is performed after the pre-scalar.

Type C timer

Type C timer is a 16-bit timer. Most often it is used together with type B timer to form a 32- bit general purpose timer. Timers of this type, if present, in the dsPIC30F family of microcontrollers are denoted as the timer3 module and timer5 module like in dsPIC30F4013 microcontroller.. Type C timer has the following specific features:

☞a type C timer can be concatenated with a type B timer to form a 32-bit timer,

☞At least one type C timer has the ability to trigger an A/D conversion.

Concatenated 32-bit timer

The described type B and C timers, as already mentioned, could be concatenated to form a 32- bit timer. The timer4 and timer5 modules could be combined in a similar way. The formed 32-bit timer is a general purpose (GP) timer and could be configured by the control bits to operate in the following modes:

☞32-bit timer.

☞32-bit synchronous counter.

It is significant to note that the timer2 and timer3 modules could independently operate as 16-bit timers in the all operational modes as the timer1 module. The same applies for timer4 and timer5 modules.

Timer2 and timer3 modules make use of other peripherals, Input capture or Output compare, in order to realize in a simple way a pulse-width modulated (PWM) signal or an A/D converter for triggering conversion at precise sampling times which is not possible with the timer4 and timer5 modules.

The concatenated 32-bit timer2/3 module has the ability to:

☞A/D event trigger,

☞operate in gated time accumulation mode,

☞pre-scalar select,

☞operate in IDLE state, and

☞Generate an interrupt request upon the concatenated counter register TMR2/TMR3 is equal with the preset register PR3/PR2.

Adjustment of the mode of operation of the concatenated timer2/3 module is performed by the control bits in T2CON and T3CON.

Example

Turn on and off a LED diode at port D approximately once every two seconds. The example uses the concatenated timer2 and 3 modules having 256 times slower clock than that of the dsPIC device. At each 100 000 clocks of timer1 interrupt routine Timer23Int is called and the value at port D is changed.

void Timer23Int() org 0x22

{ // Address in the interrupt vector table of

timer3

LATD = ~PORTD; // Invert port D

IFS0 = 0; // Clear interrupt request

}

void main()

{

TRISD = 0; // Port D is output

LATD = 0xAAAA; // Initial value at port D is set

IPC1 = IPC1 | 0x1000; // Timer3 priority is 1

 

IEC0 = IEC0 | 0x0080; // Timer3 interrupt enabled

PR2 = 34464; // Interrupt period is 100 000 clocks

PR3 = 0x0001; // Total PR3/2=1*65536 + 34464

T2CON = 0x8038; // Timer2/3 is enabled, internal clock is

divided by 256

while(1) asm NOP; // Endless loop

}

Input Capture

The input capture module has the task of capturing the current value of the timer counter upon an input event. This module is mainly used for the frequency or time period measurements and pulse measurements (e.g. mean count rate measurement). microcontroller dsPIC30F4013 contains 4 input capture modules, whereas dsPIC30F6014A contains 8 input capture modules.

The input capture module has multiple operating modes selectable via the IC x CON register (control bit ICM<2:0>):

☞Select by external input signal mode,

☞Interrupt by external input signal mode.

The input capture module contains a four-level FIFO buffer. By setting the control bits a user can select the number of captures from the counter before the input capture module generates an interrupt request.

External signal capture input mode

In the family of dsPIC30F microcontrollers the select by external input signal mode implies selecting the value from the TMR2 or TMR3 counter depending on the external input signal at pin IC x. The capture can be carried out depending on the external input signal:

☞on every falling edge of input signal applied at the IC x pin,

☞on every rising edge of input signal applied at the IC x pin,

☞on every rising and every falling edge of input signal applied at the IC x pin,

☞on every fourth rising edge of input signal applied at the IC x pin,

☞on every 16th rising edge of input signal applied at the IC x pin,

The selection of the input capture mode is carried out by setting the control bits ICM<2:0> in the register IC x CON<2:0>. Also, by setting the control bits ICM<2:0> the reduction ratio in the pre-scalar 1, 4, or 16 is set.

NOTE: The counter register of the input capture module is cleared upon RESET or switch off.

Simple capture mode

The simple capture mode is the mode of the input capture module when the capture is done on every rising or falling edges of the external input signal at the input pin. In this mode the logic of the input capture module detects the change of the logical level at the input pin, synchronizes the change with the phase of the internal clock, captures the value of the counter & puts it into the buffer memory.

The pre-scalar operates with the ratio 1:1, i.e. without reduction.

Since the input capture module comprises a four-level FIFO buffer, by setting the control bit ICI<1:0> it is possible to select the number of captures before an interrupt is generated. In this way capturing of fast external signals is made possible because while the counter values are captured and put into the buffer, it is possible to read previous values in the buffer and transfer them to the data memory.

Selection of the counter of the timer module which is to be captured is done by setting the control bit ICTMR. It is possible to select the 16-bit counters TMR2 or TMR3.

Example

It demonstrates the operation of the input capture module in the simple capture mode. The value of the counter of timer2 TMR2 is captured on the falling edge of the IC1 signal (pin RD8). The captured value is put to port B.

void Input1CaptureInt() org 0x16

{

LATB = IC1BUF; //Read captured values

IFS0.F1 = 0; //Clear bit IC1IF (IFS)

}

void main()

{

TRISB = 0; //PORTB is output

LATB = 0; //Initial value at PORTB

TRISD = 0x0100; //Select pin IC1 (RD8) as input

IPC0 = IPC0 | 0x0010; //Interrupt priority level

IEC0 = IEC0 | 0x0002; //Interrupt Input Compare

PR2 = 0xFFFF; //PR2 register at maximum

T2CON = 0x8030; //Timer 2 with pre-scalar 1:256

IC1CON = 0x0082; //Configuration of Input Capture

selected TMR2, capture on falling edge

while(1) asm NOP; //Endless loop

}

During interrupt routine clearing the interrupt Input Capture module request flag is mandatory and the captured value is read form the FIFO buffer. In setting timer2 the preset register PR2 is set at the maximum value in order to ensure operation of the timer in the free-running mode over the full range of values, from 0 to 65535. Input Capture module 1 is configured to capture values of timer 2 on falling edge of the signal at IC1 pin.

Pre-scalar capture mode

In this mode of operation of the input capture module the external signal is pre-scaled by the ratio 1:4 or 1:16 by setting the control bit ICM<2:0> to the values 100 or 101 respectively. In this way it is possible that the input capture module captures total value of the counter TMR2 or TMR3 for 4 or 16 periods of the external signal at the pin ICx. This is the way of measuring mean count rate by averaging 4 or 16 periods of an external input signal.

By setting the control bit IC1<1:0> (IC x CON<6:5>) it is also possible, like in the simple capture mode, to select the number of captures after which can interrupt request is generated. The selection of the timer module which is to be sampled is done by setting the control bit ICTMR (IC x CON<7>).

NOTE

If the time base is incremented by each instruction cycle, then the result of capturing will be available in the FIFO buffer one or two instruction cycles after the synchronous change at the input pin IC x, in phase with the internal clock of the microcontroller.

Before the operational mode is changed the input capture module should be turned off, i.e. the control bits ICM<2:0> cleared. If the mode is changed without clearing ICM<2:0>, there is a residual content in the pre-scalar counter which leads to the premature sampling and interrupt request generation.

Example

This example demonstrates the operation of the input capture module in the pre-scalar capture mode. The example shows capturing the values of the timer2 counter TMR2 on each fourth rising edge if the IC1 signal (pin RD8). The captured value is put to port B.

void Input1CaptureInt() org 0x16

{

LATB = IC1BUF; //Read captured value and put to PORTB

IFS0.F1 = 0; //Clear IC1IF bit (IFS)

}

void main()

{

TRISB = 0; //PORTB iz output

LATB = 0; //Initial value at PORTB

TRISD = 0x0100; //Select pin IC1 (RD8) as input

IPC0 = IPC0 | 0x0010; //Interrupt priority level is

 

 

IEC0 = IEC0 | 0x0002; //Interrupt Input Capture1 enable

PR2 = 0xFFFF; //PR2 register at maximum

T2CON = 0x8030; //Timer 2 with pre-scalar 1:256

IC1CON = 0x0084; //Configuration of Input Capture1,

selected TMR2, capture on each 4th rising edge

while(1) asm NOP; //Endless loop

}

During interrupt routine clearing the interrupt Input Capture module request flag is mandatory and the captured value is read form the FIFO buffer.

In setting timer2 the preset register PR2 is set at the maximum value in order to ensure operation of the timer in the free running mode over the full range of values, from 0 to 65535.

Input Compare module 1 is configured to capture values of timer 2 on each fourth rising edge of the signal at IC1 pin.

Edge detection mode

Capturing the value of TMR2 or TMR3 counter can be done on every rising and every falling edge of the external input signal applied to the IC x pin.

The edge detection mode is selected by setting the ICM<2:0> (IC x CON<2:0>) control bits to 001.

In this mode the pre-scalar counter cannot be used.

The input capture module interrupt request is generated on every rising and every falling edge (IC x IF bit is set).

It not possible to generate an interrupt request after 2, 3, or 4 captures by setting the control bits ICI<1:0> (IC x CON<6:5>) because in this mode they are ignored.

Every capture event generates an interrupt. As a consequence no overflow of the FIFO buffer is possible.

NOTE

If the time base is incremented by each instruction cycle, then the result of capturing will be available in the FIFO buffer one or two instruction cycles after the synchronous change at the input pin IC x, in phase with the internal clock of the microcontroller.

Output Compare Module

The output compare module has the task of comparing the value of the time base counter with the value of one or two compare registers depending on the Operation mode selected. It is able to generate a single output pulse or a sequence of output pulses when the compared values match; also, it has the ability to generate interrupts on compare match events.

The 4011 controller has 4 output compare modules whereas controller dsPIC6014A has 8. Each output compare channel can select which of the time base counters, TMR2 or TMR3; will be compared with the compare registers. The counter is selected by using control bit OCTSEL.

The output compare module has several modes of operation selectable by using control bits OCM<2:0>:

☞Single compare match mode,

☞Dual compare match mode generating either one output pulse or a sequence of output pulses,

☞Pulse Width Modulation (PWM) mode.

NOte

It is advisable, before switching to a new mode, to turn off the output compare module by clearing control bit OCM<2:0>.

Single compare match mode

When control bits OCM<2:0> are set to 001, 010, or 011, the output compare module is set to the Single compare match mode. Now, the value loaded in the compare register OC x R is compared with time base counter TMR2 or TMR3. On a compare match event, depending on the value of OCM<2:0>, at the OC x output pin one of the following situations is possible:

☞OC x pin is high, initial state is low, and interrupt is generated,

☞OC x pin is low, initial state is high, and interrupt is generated,

☞State of OC x pin toggles and interrupt is generated.

Single compare match, pin OC x driven high

In order to configure the output compare module for this mode, control bits OCM<2:0> are set to 001. Also, the time base counter (TMR2 or TMR3) should be selected. Initially, output pin OC x is set low and will stay low until a match event occurs between the TMR y and OC x R registers. One instruction clock after the compare match event, OC x pin is driven high and will remain high until a change of the mode or the module is disabled. TMR y goes on counting. Two instruction clocks after OC x pin is driven high, the interrupt, OC x IF flag, is generated.

Single compare match, pin OC x driven low

In order to configure the output compare module for this mode, control bits OCM<2:0> are set to 010. Also, the time base counter should be enabled. Initially, output pin OC x is set high and it stays high until a match event occurs between the TMR y and OC x R registers. One instruction clock after the compare match event OC x pin is driven low and will remain low until a change of the mode or the module is disabled. TMR y goes on counting.

Two instruction clocks after OC x pin is driven low, the interrupt flag, OC x IF, is generated.

Single compare match, pin OC x toggles

In order to configure the output compare module for this mode, control bits OCM<2:0> are set to 011. Also, the time base counter should be enabled. Initially, output pin OC x is set low and then toggles on each subsequent match event between the TMR y and OC x R registers.

OCX pin is toggled one instruction clock the compare match event. TMR y goes on counting. Two instruction clocks softer the OCX pin is toggled, the interrupt flag, OC x F, are generated.

Example

Output compare module 1 is in the single compare mode: toggle current output of pin OC1. The output compare module compares the values of OC1R and TMR2 registers; on equality, the output of OC1 pin is toggled.

void Output1CompareInt() org 0x18

{ //OC1 address in the interrupt vector table

IFS0.F2 = 0; //Clear Interrupt Flag

}

void main()

{

TRISD = 0; //OC1 (RD0) is output pin

IPC0 = IPC0 | 0x0100; //Priority level of interrupt

IEC0 = IEC0 | 0x0004; //Output compare 1 enable

 

OC1R = 10000; //OCR=TMR2

PR2 = 0xFFFF; //PR2 value maximal,

T2CON = 0x8030; //Time base 2 pre-scalar 1:256

OC1CON = 0x0003; // Configure Output compare 1

while(1) asm NOP; //Endless loop

}

In the interrupt routine the request for the flag Output compare interrupt module is reset. At setting time base 2, preset register PR2 is set to the maximum value in order to enable the free running mode over the whole range, 0-65335. The value of OC1R defines the time of the change of state of pin OC1, i.e. of the duty cycle. The output compare module is configured to change the state of pin OC1 on single compare match with the value of OC1R.

Dual compare match mode

When control bits OCM<2:0> are set to 100 or 101, the output compare module is configured for the dual compare match mode.

In this mode the module uses two registers, OC x R and OC x RS, for the compare match events.

The values of both registers are compared with the time base counter TMR2 or TMR3. On a compare match event of the OC x R register and register TMR2 or TMR3 (selectable by control bit OCTSEL), the leading edge of the pulse is generated at the OC x pin; the register OC x RS is then compared with the same time base register and on a compare match eve net, the trailing edge at the OC x pin is generated.

Depending on the value of control bit OCM<2:0> at the output pin OC x is generated:

☞single pulse and an interrupt request,

☞A sequence of pulses and an interrupt request.

Dual compare match mode, single output pulse at pin OC x

When control bits OCM<2:0> are set to 100, the output compare module is configured for the dual compare match (OC x R and OC x RS registers), single output pulse mode.

By setting the control bits OCTSEL the time base counter for comparison is selected. v. Two instruction clocks after pin OC x is driven low, an interrupt request OC x IF for the output compare module is generated. Pin OC x will remain low until a mode change has been made or the module is disabled. If the contents of time base register PR y

The Pulse Width Modulation (PWM) Mode

When control bits OCM<2:0> are set to the values 110 or 111, the output compare module is configured for the pulse width modulation (PWM) mode. The PWM mode is available without fault protection input or with fault protection input. For the second PWM mode the OC x FA or OC x FB input pin is used. Fig. shows an example of microcontroller dsPIC30F4013 connection to the inverter including the feedback error signal.

pulse-width-modulation

PWM mode without fault protection input

When control bits OCM<2:0> are set to 110, the output compare module operates in this mode. In PWM mode the OC x R register is a read only slave duty cycle register.

The OC x RS is a buffer register written by the user to update the PWM duty cycle. On every timer to period register match event (end of PWM period), the duty cycle register, OC x R, is loaded with the contents of OC x RS.

The interrupt flag is asserted at the end of each PWM period.

When configuring the output compare module for PWM mode of operation, the following steps should be taken:

☞Set the PWM period by writing to the selected timer period register, PR y.

☞Set the PWM duty cycle by writing to the OC x RS register.

☞Write the OC x R register with the initial duty cycle.

☞Enable interrupts for the selected timer.

☞Configure the output compare module for one of two PWM operation modes by writing 100 to control bits OCM<2:0> (OC x CON<2:0>).

☞Set the TMR y pre-scale value and enable the selected time base.

NOTE

The OC x R register should become a read only duty cycle register before the output compare module is first enabled (OCM<2:0>=000).

PWM mode with fault protection input pin

When the control bits OCM<2:0> are set to 111, the output compare module is configured for the PWM mode of operation. In addition to the output pin OCX the use is made of the signal from the input pin OC x FA for the output compare channels 1 to 4 or from the input pin OC x FB for the output compare channels 5 to 8. The signal at input pin OC x FA or OC x FB is a feedback error signal of the inverter related to a possible hazardous state of operation of the inverter. If the input pin OC x FA or OC x FB is low, the inverter is considered to be in a hazardous state.

Then the output OC x pin of the output compare module operating in the PWM mode is disabled automatically and the pin is driven to the high impedance state. The user may elect to provide a pull-down or pull-up resistor in order to define the state of OC x pin which is in this state disconnected from the rest of the output compare module.

In the state of inverter fault, upon detection of the fault condition and disabling of pin OC x, the respective interrupt flag is asserted and in the register OC x CON the OCFLT bit (OC x CON<4>) is set. If enabled, an interrupt of the output compare module will be generated.

NOTE

The external fault pins, OC x FA or OC x FB, while the output compare module operates in PWM mode with fault protection input pin, will continue to protect the module while it is in SLEEP or IDLE mode.

PWM period and duty cycle calculation

PWM period

The PWM period, specified by the value in the PR y register of the selected timer y, is calculated by:

TPWM = (PR y +1) * TCY * (TMR y pre-scale value),

And the PWM frequency by:

PWM Frequency = 1/TPWM.

Example

Calculation of the PWM period for a microcontroller having a 10MHz clock with x4 PLL, Device clock rate is 40MHz. The instruction clock frequency is FCY=FOSC/4, i.e. 10MHz.

Timer 2 pre-scale setting is 4. Calculate the PWM period for the maximum value PR2=0xFFFF=65535.

TPWM = (65535+1) x 0.1µs x (4) = 26.21 ms, i.e. PWM frequency = 1/TPWM = 38.14 Hz.

PWM duty cycle

The PWM duty cycle is specified by the value written to the register OC x RS. It can be written to at any time within the PWM cycle, but the duty cycle value is latched into OC x R when the PWM period is completed. OC x R is a read only register. This provides a double buffering for the PWM duty cycle.

If the duty cycle register, OC x R, is loaded with 0000, the duty cycle is zero and pin OC x will remain low throughout the PWM period.

If the duty cycle register is greater that PR y, the output pin OC x will remain high throughout the PWM period (100% duty cycle).

If OC x R is equal to PR y, the OC x pin will be high in the first PWM cycle and low in the subsequent PWM cycle.

NOTE

In order to achieve as fine as possible control of PWM, it is necessary to enable as high as possible duty cycle adjustment. This is accomplished by adjusting the pre-scale value, clock value, and PWM frequency to achieve the highest possible value of PR y thus achieving the highest number of adjustment levels, i.e. the highest resolution.

Maximum resolution

The maximum resolution is calculated by the following formula:

Max PWM resolution [bits] =

(log10TPWM – log (TCY x pre-scale value TMR y)) / log102

Example

Calculation of the PWM period for a microcontroller having a 10MHz clock with x4 PLL, Device clock rate is 40MHz. The instruction clock frequency is FCY=FOSC/4, i.e. 10MHz.

Timer 2 pre-scale setting is 4. Calculate the maximum resolution for PWM frequency 48Hz.

Max PWM resolution [bits] =

(log10 (1/48) – log10 (0.1µs x 4)) / log102 = 15.66 bits.

For this value of the PWM period and other selected parameters (pre-scale value, clock) it turns out that the PWM mode operates with almost maximum resolution.

A/D Converter

A/D (Analogue-to-Digital) converter is a “mixed signal” circuit which performs digitization of the external analogue signals. In the dsPIC30F family there are two microcontroller versions one with 10-bit and the other with 12-bit A/D converter. It has been shown in practice that for the control or regulation systems the 10-bit A/D converters gave satisfactory solutions. The additional bits in the A/D converters in these applications are almost unusable because they are masked by the high levels of electro-magnetic noise. In the measuring systems the practice showed that with the 12-bit converters one could achieve a good compromise between the sampling rate and accuracy.

10 bit A/D Converter

The 10-bit A/D converter microcontrollers could sample up to 16 analogue inputs with the frequency of 500 kHz applying for the successive approximation (SAR) conversion.

The successive approximation conversion method is one of the basic types of A/D conversion. It is carried out in several steps until the input voltage is equal to the internally generated voltage.

The speed of conversion of this type of A/D converters is limited, but they are sufficiently fast for most of the general purpose applications. This 10-bit A/D converter has the ability of using external voltage references, simultaneous sampling of up to four analogue inputs in the Sample/Hold amplifiers (sampling of several signals at one time is possible), automatic channel scan mode, and selectable conversion trigger source.

The conversion result is loaded to a 16-word buffer register in four selectable output formats (two integers and two floating point). In addition, the A/D converter could operate in SLEEP or IDLE mode. The performance of microcontrollers having 12-bit A/D converter is somewhat inferior to this, but their conversion accuracy is higher.

They could sample up to 16 analogue inputs with 100 kHz frequency applying the successive approximation conversion. The converter can use the external voltage references, sample only one of the 16 analogue inputs in the Sample/Hold amplifier, it has automatic channel scan mode and selectable conversion trigger source. Like the 10-bit converter, the conversion result is loaded to a 16-word buffer register in four selectable output formats (two integers and two floating point). In addition, the A/D converter could operate in SLEEP or IDLE mode.

12-bit A/D converter

The A/D converter possesses 12 analogue inputs (other microcontrollers of the dsPIC30F family could have up to 16 analogue inputs) connected via an analogue multiplexer to the Sample/Hold amplifier. There are two analogue inputs for setting an external reference voltage. The output of the Sample/Hold amplifier is the input to the converter, based on successive approximations.

The 12-bit A/D converter can be configured that the reference voltages are the supply voltages (AVDD, AVSS) or the external reference voltages (VREF+, VREF-). This A/D converter can operate in SLEEP mode which is very useful for the purpose of minimizing conversion noise owing to the power supply.

For controlling the process of A/D conversion the A/D converter has six 16-bit control registers: registers ADCON1, ADCON2, ADCON3 serving for selecting the mode of the A/D converter, register ADCHS serving for selecting analogue inputs used for A/D conversion, register ADPCFG serving for selecting the pin used as analogue input and the pin used as Input/output (I/O) pin, and register ADCSSL serving for selecting the analogue inputs to be scanned.

The result of A/D conversion is loaded in a «read-only» RAM buffer, 16-word deep and 12- bit wide. The result of conversion from the buffer denoted by ADBUF0, ADBUF1 ... ADBUFF is, via the output 16-bit register, read in accordance with the selected output format.

The content of the RAM buffer at locations ADBUF0 to ADBUFF cannot be written by software, but is written exclusively by the A/D converter.

A/D conversion sequence

Upon configuration of the A/D converter, the process of acquisition of samples of the input signal is started by setting the SAMP bit. The conversion may be started by various sources: programmable control bit, timer after a preset time interval, or an external event. When the conversion time is complete, the result is loaded into the RAM buffer located from ADBUF0 to ADBUFF registers. Upon completion of the A/D conversion, the bit DONE and interrupt flag are set after the number of samples defined by the SMPI control bits.

The following steps should be followed for performing an A/D conversion:

1. Configure the A/D module

☞configure the port pins as analogue inputs, voltage reference, and digital I/O pins,

☞select A/D converter input channel,

☞select A/D conversion clock,

☞select A/D conversion trigger source,

☞turn on A/D module;

2. Configure A/D interrupts (if required)

☞clear ADIF bit (IFS0,11>),

☞select A/D interrupt priority,

☞set ADIE bit (IEC0<11>);

3. Start sampling

4. Wait the required acquisition time;

5. Trigger acquisition end, start conversion;

6. Trigger acquisition end, start conversion;

7. Wait for A/D to complete, by either

☞waiting for the A/D interrupt, or

☞waiting for the DONE bit to get set;

8. Read A/D result buffer, clear ADIF bit if required.

A/D converter configuration

Select voltage reference – A/D converter configuration is started by selecting the voltage reference source. This process is performed by setting the control bit VCFG<2:0> (ADCON2<15:13>). The reference voltage could be selected to be either internal supply voltages AVDD or AVSS or external voltage references VREF+ or VREF- via the external pins.

Select the A/D conversion clock – A/D conversion rate is determined by the A/D conversion clock, the period is denoted by TAD. For performing one A/D conversion 14 periods of the TAD clock are required. The A/D converter clock is formed on the basis of the instruction clock TCY of the microcontroller. The A/D conversion period TAD, generated by a 6-bit counter, is selected by the control bits ADCS<5:0>. Period TAD is defined by the formula:

tad-formula

In order that the A/D conversion gives a correct result, it is required that the conversion time, 14TAD, is at least 10µs. From this condition one can conclude that the minimum period of the A/D converter clock is TAD = 667ns.

For the 10-bit A/D converters of the dsPIC30F family the minimum period of the clock is 154ns. Table 7-1 presents the values of the period of the A/D converter clock and the length of A/D conversion as functions of the instruction clock TCY of the microcontroller.

NOTE

☞If the clock source is the internal RC oscillator, typical values are TAD=1.5ns and VDD > 3V.

☞The value is less than the minimum value of TAD.

☞If shorter conversion time is desired, selection of another clock source is recommended.

☞A/D converter does not operate with full accuracy if the internal RC clock source operates beyond 20MHz.

Selection of analogue inputs – All Sample/Hold amplifiers have analogue multiplexers for selecting analogue input pins determined by the control bits ADCHS. The control bits ADCHS determine which analogue inputs are selected for each sample (non-inverting and inverting).

Configuring analogue port pins – The ADPCFG register specifies the input condition of device pins used as analogue inputs. A pin is configured as an analogue input when the corresponding PCFG n bit (ADPCFG) is cleared. If the corresponding PCFG n is set, the pin is configured as a digital I/O. The ADPCFG register is cleared at RESET, causing the A/D input pins to be configured for analogue inputs. The TRISB register determines whether a digital port is input or output. If the corresponding TRIS bit is set, the pin is input, if this bit is cleared, the pin is output.

Configuration of the ADPCFG and TRISB registers controls the operation of the A/D port pins.

Channel 0 input selection – The user may select any of the up to 16 analogue inputs as the input to the positive input of the Sample/Hold amplifier by setting the control bits CH0SA<3:0> (ADCHS<3:0>). The user may select either VREF- or A1 as the negative input of the channel, depending on the setting the CH0NA bit. In this way channel 0 is fully defined.

Specifying alternating channel 0 input selections – The ALTS control bit causes the module to alternate between two sets of inputs that are selected during successive samples. The inputs specified by CH0SA<3:0>, CH0NA, CHXSA, and CHXNA<1:0> are collectively called the MUX A inputs. The inputs specified by CH0SB<3:0>, CH0NB, CHXSB, and CHXNB<1:0> are collectively called the MUX B inputs.

When the ALTS control bit is set, then one input of the group MUX A and one input of the group MUX B are selected alternatively.

When this control bit is cleared, only the group MUX A inputs are selected for sampling.

Scanning through several inputs with channel 0 – Channel 0 has the ability to scan through a selected vector of inputs. The CSCNA bit (ADCON2<10>) enables the CH0 channel inputs to be scanned across a selected number of analogue inputs. When CSCNA bit is set, the CH0SA<3:0> bits are ignored. The ADCSSL register specifies the inputs to be scanned. Each bit in the ADCSSL register corresponds to an analogue input (bit 0 corresponds to AN0, bit 1 to AN1, etc.). If the bit of the corresponding input is set, the selected input is the part of the scanning sequence. The inputs are always scanned from the lower to the higher numbered inputs.

The control register ADCSSL only specifies the input of the positive input of the channel. The CH0NA bit still selects the input of the negative input of the channel during scanning.

If the alternate selection ALTS control bit is set, the scanning only applies to the MUX A (CH0SA<3:0>) input selection. The same applies for the MUX B input selection (CH0SB<3:0>) if selected by the ADCSSL control register.

NOTE

If the number of scanned inputs selected is greater than the number of samples taken per A/D converter interrupt, the higher numbered inputs will not be sampled.

The registers ADCHS, ADPCFG, and ADCSSL enable software configuration of the analogue pins AN13 – AN15 not implemented in the microcontroller dsPIC30F4013. If A/D conversion of these inputs is performed, the results are “0”.

Enabling the A/D converter module – When the ADON bit (ADCON1<15>) is set, the module is in active mode and is fully powered and functional. When the ADON bit is cleared, the module is disabled. The digital and analogue portions of the circuit are turned off for maximum current savings.

Starting A/D conversion process – start of the sampling process

Depending on the A/D converter mode selected, the sampling and conversion processes can be started manually or automatically. By starting the conversion process the sampling process on the Sample/Hold amplifier is started.

Manual start of the sampling process – Setting the SAMP bit (ADCON1<1>) causes the A/D converter to begin sampling. One of several options can be used to end sampling and complete the conversion. Sampling will not resume until the SAMP bit is once again set.

Automatic start of the sampling process – Setting the ASAM bit (ADCON1<2>) causes the A/D converter to automatically begin sampling whenever previous conversion cycle is completed. One of several options can be used to end sampling and complete the conversion.

Sampling resumes after the conversion is completed.

Stopping sampling and starting conversions

The conversion trigger source will terminate sampling and start the sequence of conversions.

The SSRC<2:0> control bits (ADCON1<7:5>) select the source of the conversion trigger.

Similarly to starting sampling process, a user can start conversions manually or automatically.

Note

The SSRC selection bits should not be changed when the A/D module is enabled (ADON=1).

If the user wishes to change the conversion trigger source, the A/D module should be disabled first by clearing the ADON bit (ADON=0).

Manual conversion start – When SSRC<2:0>=000, the conversion trigger is under software control. Clearing the SAMP bit (ADCON1<1>) starts the conversion sequence.

setting-for-samp-bit

This figure shows manual sample start by setting the SAMP bit (SAMP=1) and manual conversion start by clearing the SAMP bit (SAMP=0).

The user must time the setting and clearing the SAMP bit in accordance with the acquisition time TSAMP of the input signal.

Example

This example shows a manual sample start and a manual conversion start. The result of the A/D conversion is sent to the output of port D.

/* device = dsPIC30F6014A. Clock=10MHz */

void main()

{

TRISB = 0xFFFF; //Port B is input

TRISD = 0; //Port D is output (for ADC results)

ADPCFG = 0xFBFF; //10th channel is sampled

ADCON1 = 0; //ADC off, output format=INTEGER

//Manual start of conversion

//Manual start of sampling

ADCHS = 0x000A; //Connect RB10 on AN10 as CH0 input

ADCSSL = 0; //No scan

ADCON3 = 0x1003; (min TAD for 10MHz is 3*TCY=300ns)

ADCON2 = 0; //Interrupt completion of 1 sample/convert

ADCON1.F15 = 1; //ADC on

while (1)

{

ADCON1.F1 = 1; //Start sampling (SAMP=1)

Delay_ms(100); //Wait for 100ms (sampling ...)

 

ADCON1.F1 = 0; //Clear SAMP bit

while (ADCON1.F0 == 0)

asm NOP; //Wait for DONE bit in ADCON1

LATD = ADCBUF0; //Output result on port D

}

}

The below figure shows an example of an automatic sample start by setting the control bit ASAM (ASAM=1) and a manual conversion start by clearing the control bit SAMP (SAMP=0).

automatic-sample-start-setting-control-bit-asam

Example

This example shows an automatic sample start and a manual conversion start. The result of the conversion is sent to the output of port D.

/*device = dsPIC30F6014A Clock=10MHz*/

void main()

{

TRISB = 0xFFFF; //Port B is input

TRISD = 0; //Port D is output (for ADC results)

ADPCFG = 0xFBFF; //10th channel is sampled

ADCON1 = 0x0004; //ADC off

//Manual start of conversion

//Automatic start of sampling after conversion

ADCHS = 0x000A; //Connect AN10 as CH0 input

ADCSSL = 0; //No scan

ADCON3 = 0x1003;

ADCON2 = 0; //Interrupt upon completion of one

sample/convert

 

 

ADCON1.F15 = 1; //ADC on

while(1)

{

Delay_ms(100); //Wait for 100ms

ADCON1.F1 = 0; //Clear SAMP bit

while(ADCON1.F1 == 0)

asm nop; //Wait for DONE bit in ADCON1

LATD = ADCBUF0; //Output result on port D

}

}

External event trigger conversion start

It is often desirable to synchronize the end of sampling and the start of conversion with some external event, i.e. with an external signal source. The A/D module may use one of three sources as a conversion trigger.

External INT pin trigger – When SSRC<2:0>= 001, the A/D conversion is triggered by an active transition on the INT0 pin.

The INT0 pin may be programmed for either a rising edge input or a falling edge input.

GP timer compare trigger – This mode is also called trigger mode. By setting the control bits SSRC<2:0>=010, the conversion trigger source can be the general purpose 32-bit timer module 2/3. When the value of the TMR3/TMR2 counter register is equal to the value of the preset (period) register PR3/PR2, a special ADC event signal is generated which triggers the conversion process.

NOTE

The ability of generating an event trigger signal has only timer 3 modules. In the 16- bit mode it can initiate the start and also in the 32-bit mode it can do that in the concatenated timer 2/3. This feature does not exist for the timer module 4/5.

Motor control PWM trigger – In the microcontrollers containing this module, the start of conversion can be synchronized to the PWM time base.

When SSRC<2:0>=011, the A/D sampling and conversion time occur at any user programmable point within the PWM period. In this way the user can minimize the delay between the time when A/D conversion results are acquired and the time when the duty cycle value is updated.

The described modes of external initiation or stopping the sampling process or starting the conversion process by setting the control bits SSRC<2:0> = 001, or 010, or 011 could be combined with the automatic sample start by setting the ASAM bit.

Note

Depending on the start modes of the sampling and conversion, one obtains different sampling times. In all cases, however, it is required that sampling time TSAMP is longer than the minimum time determined by device characteristics.

Example

This example shows automatic sample start and start of conversion by timer 3. The result of the conversion is sent to the output of port D.

/*device = dsPIC30F6014A Clock=10MHz*/

void main()

{

TRISB = 0xFFFF; //Port B is input

TRISD = 0; //Port D is output (for ADC results)

ADPCFG = 0xFBFF; //10th channel is sampled

ADCON1 = 0x0040; //ADC off, output format=INTEGER

//Timer 3 starts conversion

ADCHS = 0x000A; //Connect RB10 on AN10 as CH0 input

ADCSSL = 0; //No scan

ADCON3 = 0x0F00; //TAD = internal TCY

//Sample time ends with timer 3 clock

/*TIMER3 init*/

TMR3 = 0; //Reset TIMER3 counter

 

PR3 = 0x3FFF; //PR3, number of TIMER3 clocks between two conversions start

T3CON = 0x8010; //TIMER3 ON, pre-scale 1:1

ADCON1.F15 = 1; //ADC on

ADCON1.F2 = 1; //ASAM=1, start sampling after conversion ends

while (1)

{

ADCON1.F1 = 1; //SAMP=1, start sampling

while(ADCON1.F0 == 0)

asm NOP; //Wait for DONE bit in ADCON1

LATD = ADCBUF0; //Output result on port D

}

}

Controlling sample/conversion operation

The application software may poll the SAMP and CONV bits to keep track of the A/D conversions.

Alternatively, the module can generate an interrupt (ADIF) when conversions are complete. The application software may also abort A/D operations if necessary.

Monitoring sample/conversion status – The SAMP (ADCON1<1>) and CONV (ADCON1<0>) bits indicate the sampling state and the conversion state of the A/D, respectively. Generally, when the SAMP bit clears indicating end of sampling, the CONV bit is automatically set indicating start of conversion. Clearing of the CONV bit denotes end of conversion. If both SAMP and CONV bits are 0, the A/D is in an inactive state. In some operational modes, the SAMP bit may also invoke and terminate sampling and the CONV bit may terminate conversion.

Generating an A/D interrupt - The SMPI<3:0> bits control the generation of interrupts. The interrupt will occur after the number of sample/conversion sequences specified by the SMPI bits and re-occur on each equivalent number of samples.

The value specified by the SMPI bits will correspond to the number of data samples in the RAM buffer, up to the maximum 16.

Disabling the A/D interrupt is not done with the SMPI bit. To disable the interrupt, clear the ADIE (IEC0<11>) analogue module interrupt enable bit.

Aborting sampling – Clearing the SAMP bit while in manual sampling mode will terminate sampling, but may also start a conversion if SSRC= 000. Clearing the ASAM bit while in automatic sampling mode will not terminate an on- going sample/convert sequence, however, sampling will not automatically resume after a subsequent conversion.

Aborting a conversion – Clearing the ADON bit during a conversion will abort the current conversion. The A/D result will not be updated with the partially completed A/D conversion, i.e. the corresponding ADCBUF buffer will contain the value add the last completed conversion (or the last value written to the buffer).

Writing conversion results into the buffer

As conversions are completed, the module writes the results of the conversions into the RAM buffer. This buffer is a RAM array of sixteen 12-bit words. The buffer is accessed through the 16 address locations within the SFR space, named ADBUF0, ADBUF1... ADBUF F. User software may attempt to read each A/D result as it is generated, but this might consume too much CPU time. Generally, the module will fill the buffer with several A/D conversion results and then generate an interrupt. This allows accomplishment of high sampling rates.

Number of conversions per interrupt – The SMPI<3:0> bits will select how many A/D conversions will take place before the CPU is interrupted. This number can vary from 1 to 16 samples per interrupt. The conversion results will always be written to ADCBUF0, ADCBUF1... ADCBUF F. If SMPI<3:0>= 0000, an interrupt is generated after each conversion and the result is always written in ADCBUF0.

Note

When the BUFM bit (ADCON2<1>) is set, the user cannot program the SMPI bits to a value that specifies more than 8 conversions per interrupt.

Buffer fill mode – In this mode two 8-word groups of the RAM buffer memory will alternately receive the conversion results after each interrupt.

This mode is selected by setting the control bit BUFM (ADCON2<1>). While one group receives the A/D conversion results, the content of the other group may be moved to the data memory.

In this way the CPU time I saved and high sampling rates can be accomplished. Upon initialization of this mode, by setting the value of the SMPI bit to n (n = 8), the result of each A/D conversion will be loaded to the lower group of the RAM buffer memory, i.e. to the locations ADBUF0 to ADBUF7.

After n A/D conversions are completed, an A/D converter interrupt generated, and the interrupt routine carried out, the higher group of the RAM buffer memory, ADBUF8 to ADBUFF, is selected and the results of the next n A/D conversions (n = 8) are loaded to these locations. This mode is selected when the processor cannot unload the RAM buffer within one sample and conversion time sequence.

NOTE

In the Buffer fill mode when the BUFM bit is set, the BUFS status bit (ADCON2<7>) indicates the half of the buffer that the A/D converter is currently filling. If BUFS=0, then the A/D converter is filling the lower group, ADCBUF0 – ADCBUF7, and the user software could read conversion values from the higher group, ADCBUF8 – ADCBUFF.

If BUFS=1, then the A/D converter is filling the higher group, ADCBUF8 – ADCBUFF, and the user software could read conversion values from the lower group, ADCBUF0 – ADCBUF7.

A/D sampling requirements

For proper functioning of the A/D convertor the total sampling time should take into account the sample/hold amplifier settling time, holding capacitor charge time, and temperature.

Reading the A/D result buffer

The results of A/D conversions are loaded into the 16-word 12-bits wide RAM buffer.

Reading the RAM buffer is possible from the special function register memory locations ADBUF0 to ADBUFF in one of the four selectable formats: integer, signed integer, fractional, and signed fractional. The FORM<1:0> bits (ADCON1<9:8>) select the format.

Note

The analogue inputs of the A/D converter are diode protected against over voltages.

In case that the voltage at an analogue input is lower by 0.3V than VSS or higher by 0.3V than VDD the corresponding diode will become forward biased. If there is no current limiting at the input, the device may be damaged.

An external RC filter is sometimes added to the analogue inputs to limit the frequency of input signals. The R component should be selected to ensure that the value of 2.5kO is not exceeded, i.e. the sampling time requirements are satisfied.

Memory Organization

The organization of memory and the mode of its use are called the memory model.

Understanding the memory model is essential for programming. The memory is divided into the program memory and data memory. The program memory is further divided into the user program space and the user configuration space.

The data memory is the space of memory locations used by a program for saving different data required for the program execution. The size of the memory space is different for different members of the dsPIC30F family.

Program memory

The dsPIC30F microcontrollers have 4M 24-bit (3 bytes) program memory address space. This does not mean that the size of the memory is 12MB (3x4M=12MB), but that is can generate 4M (4x220) different addresses.

The size of the program memory of a dsPIC30F4013 device is 16K words, i.e. 3x16K=48KB. A program can have 16K instructions less the number of auxiliary locations.

The first two locations are reserved for defining the beginning of a program. The execution of a program starts from the program memory is accessible only via even addresses. An attempt to read an odd address will result in CPU trap and device reset.

Example

The main program starts at the location 0x000120. The location 0x000000 contains GOTO instruction, and location 0x000002 contains value 0x000120. During each reset of the device, from the location 0x000000 GOTO instruction is read and from the location 0x000002 the address is read where to jump (in this case 0x000120). The program starts execution from the location 0x000120.

After the first two locations is the interrupt vector table serving, for specifying the locations where the interrupt subprograms are. It consists of 62 locations. The next two locations (0x000080 and 0x000082) are reserved for internal purposes. Then, there is the alternative interrupt vector table with another 62 locations. At the address 0x000100 is the start of the space in the program memory for the main program and subprograms. The maximum address of the program space is 0x0007FFE (total of 16K locations). After this address is the program memory configuration space.

Data memory (RAM)

Data memory (RAM) serves for storing and keeping data required for the proper operation of the programs. Depending on the program in progress, it can, but does not have to, be split into two sections. For DSP2 instruction set the data memory is considered to consist of two sections. The two data spaces are accessed by using two address generation units and separate data paths, i.e. two data can be read or written simultaneously.

Stack

A stack is a section of memory serving for temporary storage of data. It’s most important task is keeping the states of significant registers during jumps to subprograms, interrupts, traps, etc. During a jump to a subprogram in this part of the memory are kept the parameter values (if any) at the time of calling a function, value of the PC register, and the frame register W14.

The values of the PC and W14 registers are copied to the stack automatically, increasing the value of the W15 register by 6 (three times by 2). The compiler takes care to copy the parameters to the stack by adding a part of the code required for copying the parameters to the top-of-stack on each user call of a function.

A stack is a section of memory which is usually accessed sequentially. The access is possible, of course, to any memory location, even to the locations constituting the stack, but such concept is very seldom used. An increase or a decrease of the stack, however, can be done only by a sequential access.

Example of a call of void type function:

int m;

void MyProc1(int a)

{

int i;

i = a+2;

}

 

 

void main()

{

TRISB = 0;

m = 3;

asm NOP;

MyProc1(m);

m = 2;

}

The main program begins by executing the instruction TRISB = 0; after that, variable m is allocated the value 3. Then, the function is called. Now, the compiler has generated a code for copying to the stack the variable m and then jumps to the memory address where the subprogram is located.

dspic-controller-subprogram

The hardware automatically copies to the stack the program register PC (Program Counter) in order to determine the location from which the execution of the program continues after the subprogram is done. Since the width of the PC register is 24-bit, two memory locations are required for copying the PC register. The lower 16 bits (PCL) are copied first and then the higher (PCH) 8 bits (extended to 16 bits).

dspic-controller-subprogram-2

After the PC register is saved, the hardware also copies and saves the W14 register (frame register) and then writes into it the current value of the W15 register. This saves the information where the last location used by the main program is.

What the subprogram would do with the section of the stack after this address will have no influence on the execution of the main program. Therefore, the W14 register is the boundary between the local variables of the subprogram and the parameters pushed in the stack from the main program. In addition, this allows finding the address where the parameter value valid at the time of calling the subprogram is. This is done simply by subtracting from W14 the number of locations occupied by the PC and W14 registers at the moment of jumping to the subprogram.

dspic-controller-subprogram-2

SPI Module

The Serial Peripheral Interface (SPI) module is a synchronous serial interface useful for communicating with other peripheral or microcontroller devices. The examples of the peripheral devices are: serial EEPROMs, shift registers, display drivers, serial A/D converters, etc. The SPI module is compatible with Motorola’s SPI and SIOP interfaces.

Depending on the variant, the dsPIC30F family offers one or two SPI modules on a single device. E.g. dsPIC30F3014 has one SPI interface module, whereas dsPIC30F6014A has two.

A standard SPI serial port consists of the following special function registers (SPR):

☞SPI x BUF – SFR used to buffer data to be transmitted and data that have been received. It consists of two memory locations SPI x TXB (data transmit) and SPI x RXB (data receive).

☞SPI x CON – a control register that configures the module for various modes of operation.

☞SPI x STAT – a status register that indicates various status conditions.

In addition, there is a 16-bit register, SPI x SR that is not memory mapped. It is used for shifting in and out of the SPI port.

The memory mapped special function register SPI x BUF, the SPI data receive/transmit register, actually consists of two separate registers – SPI x TXB and SPI x RXB. If a user writes data to the SPI x BUF address, internally the data are written to the SPI x TXB (transmit buffer) register.

Similarly, when the user reads the received data from the SPI x BUF, internally the data are read from the SPI x RXB (receive buffer) register.

This double buffering of transmit and receive operations allows continuous data transfers in the background.

Note

The user cannot write to the SPI x TXB register or read from the SPI x RXB register directly. All reads and writes are performed on the SPI x BUF register.

The SPI module serial interface consists of the following four pins:

SD x – serial data input,

SDO x – serial data output,

SCK x– shift clock input or output,

SS x – active low slave select or frame synchronization I/O pulse.

NOTE

The SPI module can be configured to operate using 3 or 4 pins. In the 3-pin mode, the SS x pin is not used.

The SPI module has the following flexible operating modes:

☞8-bit and 16-bit data transmission/reception,

☞Master and slave modes,

☞Framed SPI modes.

8-bit and 16-bit data transfer

A control bit MODE16 (SPI x CON<10>) allows the module to communicate in either 8-bit or 16-bit modes. The functionality will be the same for each mode except the number of bits that are received and transmitted. The following should be noted in this context:

☞The module is reset when the value of the MODE16 control bit is changed.

☞Consequently, the bit should not be changed during normal operation.

☞Data are transmitted out of bit 7 of the shift register SPI x SR for 8-bit operation and out of bit 15 for 16-bit operation. In both modes data are shifted into bit ‘0’ of the SPI x SR.

☞8 clock pulses at the SCK x pin are required to shift in/out data in 8 bit mode, while 16 clock pulses are required in the 16-bit mode.

Master and slave modes

In a multi-processor operation when the SPI interface is used, the microcontrollers operate in the master and slave modes. In master mode the microcontroller is in full control of the communication since it initiates and ends the communication session and generates the SPI clock signal. In slave mode the microcontroller listens when the master initiates and ends the communication session and uses the SPI clock signal generated by the master. The figure shows the 4-pin SPI interface even though this connection can also operate with the 3-pin SPI interface.

NOTE

Using the SS x pin in slave mode of operation is optional.

Master Mode

The following steps should be taken to set up the SPI module for the master mode of operation:

1. If using interrupts:

☞Clear the SPI x IF bit in the respective IFS n register,

☞Set the SPI x IE bit in the respective IEC n register,

☞Write the SPI x IP bits in the respective IPC n register.

2. Write the desired settings to the SP x CON register with MSTEN (SPI x CON<5>) =1.

3. Clear the SPIROV (SPI x STAT<6>) status bit.

4. Enable SPI operation by setting the SPIEN (SPI x STAT<15>) control bit.

5. Write the data to be transmitted to the SPI x BUF register. Transmission will start as soon as data are written to the SPI x BUF register.

In master mode, the system clock is pre-scaled and then used as the serial clock. The pre-scaling is based on the settings in the PPRE<1:0> (SPI x CON<1:0>) and SPRE<1:0> (SPI x CON<4:2>) control bits. The serial clock generated in the master device is via the SCK x pin sent to slave devices.

Clock pulses are only generated when there are data to be transmitted /received. The CKP (SPI x CON<6>) and CKE (SPI x CON<8>) control bits determine on which edge of the clock data transmission occurs.

Slave mode

The following steps should be taken to set up the SPI module for the slave mode of operation:

1. Clear the SPI x BUF register.

2. If using interrupts:

☞Clear the SPI x IF bit in the IFS n register,

☞Set the SPI x IE bit in the respective IEC n register,

☞Write the SPI x IP bits (priority level) in the respective IPC n register.

3. Write the desired settings to the SPI x CON with MESTEN = 0.

4. Clear the SMP control bit. This specifies that input sampling is performed in the middle of the SPI clock.

5. If the CKE (SPI x CON<8>) bit is set, then the SSEN (SPI x CON<7>) control bit must be set, thus enabling 4-pin serial interface.

6. Clear the SPIROV (SPI x STAT<6>) bit and, finally, enable SPI operation by setting the SPIEN (SPI x STAT<15>) control bit.

In slave mode, data are transmitted and received as the external clock pulses appear on the SCK x pin. The CKP (SPI x CON<6>) and CKE (SPI x CON<8>) control bits determine on which edge of the clock data transmission occurs. Both data to be transmitted and data that are received are respectively written into or read from the SPI x BUF register.

Framed SPI modes

The module supports a very basic framed SPI protocol while operating in either master or slave modes. The following features are provided in the SPI module to support framed SPI modes:

☞The control bit FRMEN (SPI x CON<14>) enables framed SPI modes and causes the SS x pin to be used as a frame synchronization pulse input or output pin,

☞The control bit SPIFSD (SPI x CON<13>) determines whether the SS x pin is an input or an output, i.e. whether the module receives or generates the frame synchronization pulse.

☞The frame synchronization pulse is an active high pulse for a single SPI clock cycle.

The following two framed SPI modes are supported by the SPI module:

Frame master mode: the SPI module generates the frame synchronization pulse and provides this pulse to other devices at the SS x pin.

Frame slave mode: the SPI module uses a frame synchronization pulse received at the SS x pin.

The framed SPI modes are supported in conjunction with the master and slave modes.

The following four framed SPI configurations are available to the user: SPI master mode and frame master mode, SPI master mode and frame slave mode, SPI slave mode and frame master mode, and SPI slave mode and frame slave mode. These four modes determine whether or not the SPI x module generates the serial clock and the frame synchronization pulse.

SPI module in master mode and frame master mode

This framed SPI mode is enabled by setting the MSTEN (SPI x CON<5>) and FRMEN (SPI x CON<14>) bits to ‘1’ and SPIFSD (SPI x CON<13>) bit to ‘0’.

In this mode, the serial clock will be output continuously at the SCK x pin, regardless of whether the module is transmitting.

When the SPI x BUF is written, the SS x pin will be driven high on the next transmit edge of the SCK x clock (active edge depends on the control bit CKP). The SS x pin will be high for one SCK x clock cycle.

SPI module in master mode and frame slave mode

This framed SPI mode is enabled by setting the MSTEN (SPI x CON<5>), FRMEN (SPI x CON<14>), and SPIFSD (SPI x CON<13>) bits to ‘1’. The SS x pin is an input, and it is sampled on the sample edge of the SPI clock. When it is sampled high, data will be transmitted on the subsequent transmit edge (controlled by the CKP bit) of the SPI clock. When the transmission is completed, the interrupt flag SPI x IF is generated by the SPI x SR register. The user must make sure that the correct data are loaded into the SPI x BUF for transmission before the signal is received at the SS x pin.

SPI module in slave mode and frame master mode

This framed SPI mode is enabled by setting the MSTEN (SPI x CON<5>) bit to ‘0’, FRMEN (SPI x CON<14>) bit to ‘1’, and SPIFSD (SPI x CON<13>) bit to ‘0’. The input SPI clock will be continuous at the SCK x pin in slave mode. The SS x pin will be an output when the SPIFSD (SPI x CON<13>) bit is cleared.

Therefore, when the SPI x BUF is written, the module will drive the SS x pin high on the next transmit edge of the SPI clock. The SS x pin will be driven high for one SPI clock cycle. Data will start transmitting on the next SPI clock falling edge.

SPI module in slave mode and frame slave mode

This framed SPI mode is enabled by setting the MSTEN (SPI x CON<5>) bit to ‘0’, FRMEN (SPI x CON<14>) bit to ‘1’, and SPIFSD (SPI x CON<13>) bit to ‘1’. Therefore, both the SCK x and SS x pins will be the inputs. The SS x pin will be sampled on the sampling edge of the SPI clock (in the middle of the SPI cycle). When SS x is sampled high, data will be transmitted on the next transmit edge of SCK x.

SPI master mode clock frequency

In the master mode, the clock provided to the SPI module is the instruction cycle TCY.

This clock will then be pre-scaled by the primary pre-scaler, specified by PPRE<1:0>, and the secondary pre-scaler, specified by SPRE<2:0>. The pre-scaled instruction clock becomes the serial clock and is provided to external devices via the SCK x pin.

Note

Note that the SCK x signal clock is not free running for normal SPI modes (8-bit or 16-bit). It will only run for 8 or 16 pulses when the SPI x BUF is loaded with data. It will however, be continuous for framed modes.

The SCK x clock frequency as a function of the primary and secondary pre-scaler settings is calculated by the following equation

sck-x-clock-frequency

NOTE

SCK x clock frequencies shown in kHz. All frequencies are not supported; electrical characteristics of individual microcontrollers of <dsPIC30F family should be consulted.

Example

The example shows the use of the specialized SPI library of the C30 compiler for dsPIC microcontrollers which allows an easy initialization of the SPI module and write or read data from the transmit/receive buffer of the SPI module. The example shows the method of connecting the SPI2 module to the serial digital-to-analogue converter (DAC) MCP4921.

const char CS_PIN = 0;

unsigned int value;

 

void InitMain()

{

ADPCFG = 0xFFFF; // Set AN pins as digital

 

Spi_Init(); // Initialize SPI module

TRISF.CS_PIN = 0; // Set CS pin as output

}//~

 

// DAC increments (0..4095) --> output voltage (0..Vref)

 

void DAC_Output(unsigned int valueDAC)

{

char temp;

PORTF.CS_PIN = 0; // Select DAC module

// Send 2 bytes of valueDAC variable

temp = (valueDAC >> 8) & 0x0F; // Prepare hi-byte for transfer It's a 12-bit number, so only

// lower nibble of high byte is used

temp |= 0x30; // Set MCP4921 control bits

Spi_Write(temp); // Send data via SPI

temp = valueDAC; // Prepare lo-byte for transfer

Spi_Write(temp); // Send data via SPI

PORTF.CS_PIN = 1; // Deselect DAC module

}//~

 

void main()

 

{

InitMain();

value = 2047; // When program starts, DAC gives

// the output in the mid-range

while (1) { // Main loop

DAC_Output(value++);

if (value > 4095)

value = 0;

Delay_ms(10);

}

}//~!

Function Spi2_Init initializes the SPI module in master mode 8-bit formatted, without the SS2 pin, sampling in the middle of the SPI cycle, pre-scale 1:8, and the clock FCY: 1 low while waiting. If another format or communication speed is desired, the function Spi2_Init_Advanced instead of Spi2_Init should be used. The function Spi2_Data_Ready reads the value of the status bit SPIRBF (SPI2STAT<0>) and checks if there are data loaded into the receive buffer register. The function Spi2_Write transmits data via the SPI module.

Data reception is performed by the function Spi2_Read. The SPI modules is disabled by the function Spi2_Stop (clearing the control bit SPIEN), and the SPI module enable (setting the control bit SPIEN) is performed automatically by the function Spi2_Init or Spi2_Init_Advanced.

UART Module

The Universal Asynchronous Receiver Transmitter (UART) module is the basic serial I/O module available in the dsPIC30F device family. The UART is a full-duplex asynchronous system that can communicate with peripheral devices, such as personal computers, RS-232, and RS-485 interfaces.

The primary features of the UART module are:

☞Full-duplex 8- or 9-bit data transmission through the U x TX and U x RX pins,

☞For 8-bit data even, odd, or no parity options,

☞One or two STOP bits,

☞Fully integrated Baud-rate generator with 16-bit pre-scaler,

☞4-deep First-In-First-Out (FIFO) transmit data buffer,

☞4-deep FIFO receive data buffer,

☞Parity, framing and buffer overrun error detection,

☞Support for 9-bit mode with address detect (9th bit=1),

☞Transmit and receive interrupts,

☞Loop-back mode for diagnostic support.

Each dsPIC30F device variant may have one or more UART modules (e.g. <dsPIC30F4013 has 2 UART modules).

Fig. shows a simplified block diagram of the UART module. The UART module consists of the three key hardware elements: Baud-rate generator, asynchronous transmitter, and asynchronous receiver.

simplified-block-diagram-of-uart-module

Baud-rate generator BRG

The UART module includes a dedicated 16-bit baud rate generator with a pre-scaler. The U x BRG register controls the period of a free-running 16-bit timer:

period-of-free-running-16-bit-timer-formula

The value of the U x BRG register for a specified baud rate is given by,

baud-rate-formula

Note

The minimum baud rate is FCY/ (16•65535) for U x BRG = 0xFFFF. The maximum baud rate is FCY/16 for U x BRG = 0. Writing a new value to the U x BRG register causes the BRG timer to be cleared. This ensures that the BRG immediately starts generating the new baud rate.

UART configuration

The UART uses standard non-return-to-zero (NRZ) format consisting of one START bit, eight or nine data bits, and one or two STOP bits. To increase data transmission noise immunity, parity is supported by the hardware. The UART may be configured by the user as even (logic zero or logic one is added to make the total number of units in a message even), odd or no parity.

The most common data format is 8 bits, no parity and one STOP bit (denoted as 8, N, 1), which is the default setting.

The number of data bits and the parity are specified in the PDSEL<1:0> (U x MODE<2:1>) and the number of STOP bits in the STSEL (U x MODE<0>) control bit.

The UART baud rate is configured by setting the U x BRG register.

Note

The UART module transmits and receives the LSB first. The UART's transmitter and receiver are functionally independent, but use the same data format and baud rate.

The UART module is enabled by setting the UARTEN (U x MODE<15>) control bit. The transmit mode of the UART module is enabled by the UTXEN bit. Once enabled, the U x TX and U x RX pins are configured as an output and an input, respectively, overriding the TRIS and PORT register bit settings for the corresponding I/O port pins.

The U x TX is at logic '1' when no transmission is taking place. The UART module is disabled by clearing the UARTEN control bit. This is the default state after any RESET.

If the UART module is disabled, all UART pins operate as port pins under the control of their corresponding PORT and TRIS bits. Disabling the UART module resets the FIFO buffers to empty states and the baud rate counter is reset.

When the UARTEN bit is cleared, all error and status flags associated with the UART module: URXDA, OERR, FERR, PERR, UTXEN, UTXBRK, and UTXBF are cleared, whereas the RIDLE and TRMT bits are set to '1'. Other control bits are of no influence as long as UARTEN= 0. Clearing the UARTEN bit while the UART is active will abort all pending transmissions and receptions and reset the module. Re-enabling the UART will restart the UART in the same configuration.

Some dsPIC30F devices have an alternative set of UART transmit and receive pins that can be used for serial communication.

These are very useful when the primary UART pins are shared by other peripherals. The alternate I/O pins are enabled by setting the ALTIO control bit. If ALTIO=1, the U x ATX and U x ARX pins are used by the UART module, instead of U x TX and U x RX.

UART transmitter

The heart of the transmitter is the transmit shift register U x TSR where parallel data (9-bit word) are converted to serial data sequences.

The shift register obtains its data from the transmit FIFO buffer, T x TXREG. The write-only U x TXREG register is loaded with data by the user software.

The U x TXREG is not loaded until the STOP bit has been transmitted from the previous load. As soon as the STOP bit is transmitted, the U x TSR is loaded with new data from the U x TXREG register (if available).

Note

The registers U x TXREG and U x TSR are 9-bit wide, i.e. data write to the transmit FIFO buffer through the register U x TXREG is done in bytes (8-bit). The U x TSR register is not mapped in data memory, thus it is not available to the user.

The UART transmission is enabled by setting the UTXEN enable bit (UXSTA<10>). The actual transmission will not occur until the UXTXREG has been loaded with data and the baud rate generator has produced a shift clock, in accordance with the value in the register UXBRG.

The transmission can also be started by first loading the UXTXREG register and the setting the UTXEN enable bit.

Clearing the UTXEN bit during a transmission will cause the transmission to be aborted and will reset the transmitter. As a result, the UXTX pin will revert to a high-impedance state.

In order to select 9-bit transmission, the PDSEL<1:0> bits (UXMODE<2:1>) should be set to '11' and the ninth bit should be written to the 9th location of the UX TXREG register (UXTXREG<8>). A word (16-bit) should be written to UXTXREG so that all nine bits are written at the same time.

NOTE

There is no parity in the case of 9-bit data transmission.

The data transmit FIFO buffer consists of four 9-bit wide memory locations. The UXTXREG register provides user access to the next available buffer location. The user may write up to 4 words in the buffer. Once the first location in the transmit FIFO buffer is loaded to the shift register UXTSR, that location becomes available for new data to be written and the next location is sourced to the UXTSR register. The UTXBF status bit is set whenever the buffer is full (all four locations). If a user attempts to write to a full buffer, the new data will not be accepted into the FIFO.

Note

The FIFO is reset during any device RESET, but is not affected when the device enters SLEEP or IDLE mode or wakes up from SLEEP or IDLE mode.

Transmit interrupt

The transmit interrupt flag (UXTXIF) is located in the corresponding interrupt flag status (IFS) register. The UTIXSEL control bit (UXSTA<15>) determines when the UART will generate a transmit interrupt.

- If UTXISEL = 0, an interrupt is generated when a word (8- or 9-bit) is transferred from the transmit FIFO buffer to the transmit shift register (UXTSR). This implies that the transmit buffer has at least one empty word. An interrupt is generated very often. If the UART module is to operate in this mode, it is required that the corresponding interrupt service routine is very quick, i.e. it should be completed before the transmission of the next word.

- If UTXISEL = 1, an interrupt is generated when a word is transferred from the transmit FIFO buffer to the transmit shift register (UXTSR) and the transmit buffer is empty. Since an interrupt is generated only after all 4 words have been transmitted, this 'block transmits' mode is useful if the interrupt service routine cannot be performed very quickly.

Note

When the UTXEN enable bit is set, an interrupt request will be generated. The interrupt request should be reset by the user software. If UTXISEL = 0, an interrupt request will be generated on setting the UTXEN since there is at least one empty location in the transmit FIFO buffer; if UTXISEL = 1, an interrupt request will be generated on setting the UTXEN since the transmit FIFO buffer is empty.

While the UXTXIF flag bit indicates the status of the UXTXREG register, the TRMT (UXSTA<8>) status bit shows the status of the UXTSR register. The TRMT status bit is a read only bit, which is set when the UXTSR register is empty.

No interrupt logic is tied to this bit, so the user has to poll this bit in order to determine if the UXTSR register is empty.

Setup for UART transmit

When setting up a transmission, the following steps should be undertaken:

☞Initialize the UXBRG register for the appropriate baud rate.

☞Set the number of data bits, number of STOP bits, and parity selection by writing to the PDSEL<1:0> and STSEL bits.

☞If transmit interrupts are desired, set the UXTXIE control bit in the corresponding interrupt enable control register (IEC). Specify the interrupt priority using the control bits in the corresponding interrupt priority control register (IPC). Select the transmit interrupt mode by writing the UTXISEL bit.

☞Enable the UART module by setting the UARTEN (UXMODE<15>) bit.

☞Enable the transmission by setting the UTXEN (UXSTA<10>) bit. This will also set the transmit interrupt flag UXTXIF bit. During the initialization, the interrupt request of the UART module transmitter UXTXIF bit should be cleared. Also in the interrupt service routine the interrupt request UXTXIF should be cleared.

☞Finally, load data to the transmit FIFO buffer by writing to the UXTXREG register. If 8-bit transmission is used, load a byte (8-bits). If 9-bit transmission has been selected, load a word (9-bits, higher bits are ignored).

Note

Sending a break character does not generate a transmitter interrupt.

UART receiver

The heart of the receiver is the receive shift register UXRSR where a serial sequence is converted to a parallel word (9- bit word). After sampling the UXRX pin for the STOP bit, the received data in UXRSR are transferred to the receive FIFO buffer, if it is empty.

The data on the UXRX pin are sampled three times by a majority detect circuit to determine if a high or a low level is present at the UXRX pin.

The FIFO receive data buffer consists of four 9-bit wide memory locations. The access to the contents of the receive FIFO buffer is via the UXRXREG read-only register. It is possible for 4 words of data to be received and transferred to the FIFO buffer and a fifth word to begin shifting data to the UXRSR register before a buffer overrun occurs. When the FIFO is full (four characters) and a fifth character is fully received into the UXRSR register, the overrun error bit OERR will be set.

The word in UXRSR will be kept, but further transfers to the receive FIFO are inhibited as long as the OERR bit is set. The user must clear the OERR bit in software to allow further data to be received. Clearing the OERR bit, clears the receive FIFO buffer.

Note

The UXRSR register neither is nor mapped in data memory, so it is not available to the user.

The data in the receive FIFO should be read prior to clearing the OERR bit. The FIFO is reset when OERR is cleared, which causes data in the buffer to be lost.

Receive interrupt

The URXISEL<1:0> (UXSTA<7:6>) control bit determines when the UART receiver generates an interrupt. The UART receive interrupt flag (UXRXIF) is located in the corresponding interrupt flag status, IFS register.

If URXISEL<1:0> = 00 or 01, an interrupt is generated each time a data word is transferred from the receive shift register to the receive FIFO buffer. There may be one or more characters in the receive FIFO buffer.

If URXISEL<1:0> = 10, an interrupt is generated when a word is transferred from the receive shift register to the receive FIFO buffer and as a result, the receive buffer contains 3 or 4 characters.

If URXISEL<1:0> = 11, an interrupt is generated when a word is transferred from the receive shift register to the receive FIFO buffer and as a result, the receive buffer contains 4 characters, i.e. becomes full.

Switching between the three interrupt modes during operation of the UART module is possible. The URXDA bit indicates whether the receive FIFO buffer is empty. This bit is set as long as there is at least one character to be read from the receive buffer. URXDA is a read only bit.

The URXDA and UXRXIF flag bits indicate the status of the UXRXREG register. The RIDLE bit shows the state of the shift register UXRSR.

The RIDLE status bit is a read only bit, which is set when the receiver is IDLE (i.e. the UXRSR register is empty and there is no current data reception).

No interrupt logic is tied to this bit, so the user has to poll this bit in order to determine if the UXRSR is IDLE.

Setup for UART reception

When setting up a reception, the following steps should be undertaken:

☞Initialize the UXBRG register for the appropriate baud rate.

☞Set the number of data bits, number of STOP bits, and parity selection by writing to the PDSEL<1:0> (UXMODE<2:1>) and STSEL (UXMODE<0>) bits.

☞If receive interrupts are desired, set the UXTXIE control bit in the corresponding interrupt enable control register (IEC). Specify the interrupt priority using the UXRXIP<2:0> control bits in the corresponding interrupt priority control register (IPC). Select the transmit interrupt mode by writing the URXISEL (UXMODE<15>) bit.

☞Enable the UART module by setting the UARTEN (UXMODE<15>) bit.

☞Receive interrupts will depend on the URXISEL<1:0> control bit settings. If receive interrupts are not enabled, the user can poll the URXDA bit to check the contents of the receive FIFO buffer. The UXRXIF bit should be cleared during initialization.

☞Finally, read data from the receive FIFO buffer via the UXRXREG register. If 8-bit mode is used, read a byte (8-bits). If 9-bit mode has been selected, read a word (16- bits).

Example

This simple example demonstrates usage of C30 UARTX libraries, through a 'loopback' interface. The data being sent to dsPIC through UART and sent back. The example also shows the interconnection of the UART module and the RS-232 transceiver and the connection of the UART module to the serial port of a PC.

unsigned rx1;

void main()

{

Uart1_Init (9600); // initialize USART module

//--- un-comment the following lines to have Rx and Tx pins on their alternate locations. This is used to free the pins for other module, namely the SPI.

U1MODEbits.ALTIO = 1;

Delay_ms (10); // pause for usart lines stabilization

rx1 = Uart1_Read_Char (); // perform dummy read to clear the register

Uart1_Write_Char ('s'); // signal start

 

 

while (1)

{

if (Uart1_Data_Ready()) { // check if there is data in the buffer

rx1 = Uart1_Read_Char (); // receive data

Uart1_Write_Char (rx1); // send data back

}

}

}//~!

The program initializes the UART module in receive and transmit 8-bit format mode, without parity, and with one stop bit. If another format is to be initialized, the function Uart1_Init_Advanced instead of Uart1_Init must be used. In this way it is possible to setup 9- bit data or perhaps 8-bit data with an EVEN or ODD parity bit. Also it is possible to select one or two STOP bits. The function Uart1_Data_Ready the value of the status bit URXDA (U1STA<0>) is read and the presence of data in the receive FIFO buffer is checked. The function Uart1_Write_Char, ASCII character and text are sent respectively via the transmitter of the UART module.

Data reception, ASCII character is realized by the function Uart1_Read_Char.

UART in loopback mode

The UART module has the ability to operate in the loopback mode. This mode allows performing the corresponding self-tests. In order that the UART module operates in the loopback mode, it is required that the LPBACK (UXMODE<6>) control bit is set. In this mode the UXTX output is internally connected to the UXRX input, and the UXRX pin is disconnected from the internal UART receive logic. However, the UXTX pin still functions normally. Sending a message by the UART transmitter causes the reception of this message by the UART receiver. This allows checking if the UART module functions correctly.

To configure the UART module to operate in this mode, the following steps should be taken:

☞Configure UART for the desired mode of operation.

☞Set LPBACK=1 to enable loopback mode.

☞Enable transmission by setting the UARTEN (UXMODE<15>) and UTXEN (UZSTA<10>) control bits.

Auto baud support

To allow the system to determine baud rates of the received characters, the UXRX input can be internally connected to a selected input capture channel.

To operate in this mode, the ABAUD bit (UXMODE<5>) should be set and the UXRX pin is internally connected to the input capture channel. The corresponding ICX pin is disconnected from the input capture channel.

The input capture channel used for auto baud support is device specific. E.g. for dsPIC30F for auto baud support of the UART1 module, the input capture module IC1 is used, whereas for UART2 the input capture module IC2 is used.

This mode is only valid when the UART is enabled (UARTEN=1) and the loopback mode is disabled (LPBACK=0). Also, the user must program the capture module to detect the falling and rising edges of the START bit.

I2C (Inter Integrated Circuit) module

The Inter Integrated Circuit (I2C) module is a serial interface primarily intended for communication with other peripheral or microcontroller devices. Examples of the peripheral devices are: serial EEPROM memories, shift registers, display drivers, serial AD converters, etc. In the dsPIC30F family of devices the I2C module can operate in the following systems:

☞the dsPIC30F device is a slave device,

☞the dsPIC30F device is a master device in a single-master environment (slave may also be active),

☞ThedsPIC30F device acts as a master/slave device in a multi-master system (bus collision detection and arbitration available).

The I2C module contains independent I2C master logic and I2C slave logic each generating interrupts based on their events.

In multi-master systems, the software is simply partitioned into master controller and slave controller. When the master logic is active, the slave logic remains active also, detecting the state of the bus and potentially receiving messages from it-self or from other I2C devices. No messages are lost during multi-master bus arbitration.

In a multi-master system, bus collision conflicts with other masters in the system are detected and the module provides a method to terminate and then restart the messages.

The I2C module contains a baud-rate generator. The baud-rate generator does not consume other timer resources in the device. The speed of operation of the module may be standard or fast and it may detect 7-bit and 10-bit addresses.

Operating modes of I2C module

The I2C module may be configured to operate in the following modes:

I2C slave, 7-bit addressing,

I2C slave, 10-bit addressing, and

I2C master, 7- or 10-bit addressing.

A standard I2C interface makes use of two pins, SCL (clock line) and SDA (data line).

The configuration of the I2C module is performed by using the following registers: I2CRV (8 bits), I2CTRN (8 bits), I2CBRG (9 bits), I2CON (16 bits), and I2CADD (10 bits).

The I2CCON and I2CSTAT are 16-bit control and status registers, respectively. The content of the I2CCON control register may be read or written and so is the content of the 10 higher bits of the I2CSTAT status register.

The lower 6 bits of the status register are read only.

The I2CRSR shift register performs parallel-series conversion of data. Data to be transmitted are written in the I2CTRN buffer register, whereas received data are read from the I2CRCV buffer register. Address of a slave device on the I2C bus is written in the I2CADD register.

The control bit A10M (I2CCON<10>) denotes whether the 7-bit or 10-bit addressing is used.

Baud-rate is defined by the I2CBRG register, i.e. it holds the baud-rate generator reload value for the I2C module baud-rate generator.

NOTE

In receive operation the shift register I2CRSR and the buffer register I2CRCV create a double-buffered receiver, i.e. when a complete message is received by the I2CRSR register, the byte transfers to the I2CRCV register and the interrupt request for the I2C module is generated. While transmitting a message the transmit buffer is not double-buffered.

I2C slave mode with 7-bit addressing

The 10-bit I2CADD register holds the slave device address. If the control bit A10M (I2CCON<10>) is cleared, address in the I2CADD is interpreted as a 7-bit address. When an address from a master device is received, only 7 lower bits are compared against the register I2CADD. If the control bit ADD10 (I2CCON<10>) is set, the value of the received address is compared in two cycles. At first, the 8 higher bits of the address are compared with the value '11110 A9 A8' (where A9 and A8 are two most significant bits of the device address held in the I2CADD register). If coincidence occurs, the lower 8 bits of the register I2CADD are compared with the 8 lower bits of the received address.

The segments of an address usable in a standard I2C communication are specified by the standard I2C protocol. Table 12-1 shows the ranges of I2C addresses supported by the family of dsPIC30F devices together with the corresponding applications.

Address

Description

0x00

General call address or starting byte

0x01 – 0x03

Range of reserved addresses

0x04 – 0x77

Range of valid 7-bit addresses

0x78 – 0x7B

Range of valid 10-bit addresses

0x7C – 0x7F

Range of reserved addresses

 

Table. Standard I2C addresses supported by the family of dsPIC30F devices

When in the slave mode, after setting the I2CEN (I2CCON<15>) enable bit, the slave function will begin to monitor the I2C bus to detect a START event. Upon detecting a START event, 8 bits are loaded to the I2CRSR shift register and the received address is compared with the one from the I2CADD register. In the 7-bit address slave mode (A10M = 0) the bits I2CADD<6:0> are compared with the I2CRSR<7:1> bits. The bit I2CRSR<0> is ignored.

The bits loaded to the shift register are sampled by the rising edge of SCL the clock.

If an address match occurs, the slave sends an ACKNOWLEDGE of the 9-bit message, and an interrupt of the I2C module is generated (the flag SI2CIF is set) on the falling edge add the ninth bit (ACK – acknowledgement). The address detection is of no influence neither on the content of the receive buffer register I2CRCV nor on the value of the bit RBF (I2CSTAT<1>) which indicates that there is a new value in the receive buffer register.

A typical standard I2C message consists of the START bit, address bits, R/W bit, acknowledge bit, data bits (e.g. in an I2C communication with the EEPROM memory within data bits are the location address bits and the contents bits which are read out or written in), and STOP bit.

A slave device transmit process is carried out as follows. Upon reception of the address part of the message containing the R/W bit, the device enters the transmit mode. It sends the ACKNOWLEDGE bit (ACK) and keeps the SCL clock signal low until the message byte is written to the transmit buffer I2CTRN.

Then, the SCL clock signal is released, the bit SCLREL is set (I2CCON<12>), and the 8-bit message is sent from the I2CRSR shift register.

The bits are sent on the falling edge of the SCL clock so that the SDA pin data are valid when the SCL clock is high. The interrupt request is generated on the falling edge of the ninth clock period irrespective of the status of the ACKLOWLEDGE (ACK) bit of the master device.

The receive sequence of a slave device comprises the following steps. Upon receiving the address part of the message which contains the R/W bit cleared, the slave device is initiated for the receive mode. The incoming bits at the pin SDA are sampled on the rising edge of the SCL clock signal. After receiving 8 bits, if they receive buffer register I2CRCV is not full or the flag RBF (I2CSTAT<1>) is not cleared or the overflow status bit (I2COV (I2CSTAT<6>) of the receive buffer register I2CRCV is not set, the received bits contained by the shift register are transferred to the receive buffer register I2CRCV.

Upon completion of the data transfer, the bit ACK is generated as the ninth bit. If the flag RBF is set, the bit ACK is not sent, but the interrupt request for the I2C is generated. In the case of the receive buffer overflow, the content of the shift register I2CRSR is not transferred to the receive buffer I2CRCV.

The status overflow bit of the receive buffer I2COV is hardware set, but the user can clear it by the software. If the bit I2COV is not cleared, the I2C module will operate irregularly, i.e. a received message is written to the receive buffer register I2CRCV if RBF was cleared, but the bit acknowledge ACK is not sent to the master device.

I2C slave mode with 10-bit addressing

The basic process of receiving and transmitting messages in the slave mode with 10-bit addressing is same as in the slave mode with 7-bit addressing; the difference is that the comparing address is more complicated.

The I2C standard specifies that after the START bit, any slave devise has to be addressed by two bytes. The control bit A10M is set meaning that a 10-bit address is in the I2CADD register. After the START bit, the received data in the shift register I2CRSR<7:1> are compared with the expression '11110 A9 A8' containing two most significant bits of the device address, A9 and A8.

If the result of the comparison is positive and the received R/W bit is cleared, an interrupt request is generated. At the same time the bit ADD10, which denotes partial match of the sent address and the slave address, is cleared.

If the sent address and the slave address do not match or if the received R/W bit is set, the status bit ADD10 is cleared and the I2C is returned to the IDLE state. If there is partial match with the upper part of the address of the slave device, the lower part of the address is received and compared with the lower part of the address register I2CADD.

If a full match occurs, an interrupt request for the I2C module is generated and the status bit ADD10, indicating a full match of the 10-bit addresses, is set. If a full match does not occur, the status bit ADD is cleared and the module returns to the IDLE state. In the case when a full match of all 10 bits is detected, the master device may send the part of the message defining whether the slave is to receive data or transmit data to the master.

If the master repeats the START bit, the upper address bit is cleared and the R/W bit is set in order to avoid that the STOP bit is generated, and the master performs initialization of the slave device for the operation transmit data. The synchronization of the read and transmit data to the master is performed in the slave device by stretching the SCL clock signal.

Whenever the slave device is to transmit data to the master, in both 7-bit and 10-bit addressing, stretching of the clock signal SCL is implemented by inserting the SCLREL bit on the falling edge of the ninth period of the clock.

In the case when the transmit buffer is empty, the status bit TBF is cleared. Stretching of the SCL clock signal in the slave mode at data transition is always performed irrespective of the state of the STREN control bit which enables stretching of the SCL clock. This is not the case in the slave mode at data reception. The clock synchronization occurs after the ninth period of the SCL clock.

Then, the slave device samples the value of the ACK acknowledgement bit and checks the value of the TBF status bit. If the ACK is low and the TBF status bit is cleared, the SCLREL bit is cleared automatically. Setting the SCLREL bit low causes setting the external SCL line low.

By the interrupt routine the user has to set the bit SCLREL before the slave device starts transmitting the message to the master. In this way the user is given the chance that in the interrupt routine writes data to be transferred to the I2CTRN transmit buffer register before the master device initiates a new transmit sequence.

Note

If the user writes data to be transferred to the I2CTRN transmit buffer register and sets the TBF bit before the falling edge of the ninth period of the SCL clock, the SCLREL bit will not be cleared and stretching of the SCL clock signal will not occur. Also, it should be noted that the SCLREL bit can be set by the software irrespective of the TBF bit.

In essence, the STREN control bit primarily serves for enabling stretching of the SCL clock signal during reception in the slave mode. When the STREN bit is set, the pin of the SCL clock signal is kept low at the end of each receive sequence in the slave mode.

Stretching of the clock signal is performed after the ninth period of the SCL clock signal during a receive sequence. On the falling edge of the ninth period of the SCL clock signal the value of the ACK ACKNOWLEDGE bit is sampled and the value of the TBF status bit is checked. If the ACK is low and the RBF status bit set, the SCLREL bit is cleared automatically.

Setting the SCLREL bit low causes setting the external SCL line low. By the interrupt routine the user has to set the bit SCLREL before the slave device starts receiving data from the master. In this way the user is given the chance that in the interrupt routine reads out received data from the I2CRCV receive buffer before the master device initiates a new receive sequence. This prevents the overflow of the I2CRCV receive buffer register.

Note

If the user reads out received data from the I2CRCV receive buffer register and clears the RBF bit before the falling edge of the ninth period of the SCL clock signal, the SCLREL bit will not be cleared and no stretching of the SCL clock signal will occur.

Also, the SCLREL bit can be set by the software irrespective of the RBF bit. Clearing the RBF bit by the user has to be done carefully during the interrupt routine to avoid overflow of the I2CRCV receive buffer register.

I2C master mode

A master device differs from a slave device in that it generates the system SCL serial clock, and STARTS and STOP bits. Each data transfer is ended by a STOP bit or by the repeated START bit. A repeated START bit also means the beginning of a new data transfer, but the I2C bus is still busy by the current communication session.

In the master mode serial data are transferred via the SDA pin in synchronism with the SCL clock signal. The first byte to be sent contains the 7-bit address of the slave (the device for whom the message is intended) and one bit for data direction R/W. In the case of data transmit the R/W bit is cleared (logic zero). The START and STOP bits are sent in order to recognize the beginning and end of a communication session, i.e. of a data transfer.

In the master mode when receiving data, the 7-bit address of the slave (the device for whom the message is intended) and one bit for data direction R/W are sent first.

In the case of data receive the R/W bit is set (logic one). Serial data are transmitted or received via pin SDA in synchronism with the SCL clock signal. Serial data are received 8 bits per cycle and each cycle is ended by sending the ACKNOWLEDGE ACK bit. The START and STOP bits are sent in order to recognize the beginning and end of a communication session.

In the master mode the transmission of a 7-bit address or of the second part of a 10-bit address is performed by writing the desired value to the transmit buffer register I2CTRN. The user writes the desired value to the transmit buffer register only when the I2C module is in the WAIT state. By writing data to the transmit buffer register I2CTRN, the status flag TBF is set and the baud-rate generator is enabled to start counting and start data transmission.

Each data bit or address bit from the shift register is sent to the SDA pin on the falling edge of the SCL clock signal. When the device is transmitting data, the transmit status flag TRSTAT (I2CSTAT<14>) is set.

The reception in the master mode is enabled by setting, using the software, the RCEN control bit. In order to set the RCEN control bit, the I2C module has to be in the IDLE state. If this is not observed, the receive enable control bit RCEN will be ignored.

The baud-rate generator starts counting and when it reaches the preset count it is reset, then the state of the SCL clock signal is changed, the ACKNOWLEGDE ACK bit is set, and the value of the SDA line is sampled on the rising edge of the clock signal and transferred to the shift register I2CRSR.

Baud-rate generator

In the master mode of the I2C module the value of the baud rate is defined by the pre-set value of the baud-rate counter BRG in the I2CBRG register. The baud-rate counter counts down from the pre-set value to zero. When zero is reached, the pre-set value BRG is written to the counter again.

In the case when the clock arbitration occurs, writing the pre-set value BRG to the baud-rate counter is performed when the pin SCL is high.

According to the I2C standard, the frequency of the clock signal FSCK is 100 kHz or 400 kHz. The user has the option of specifying the baud rate up to 1MHz. The following expression defines in the I2CBRG register the value of the desired baud rate:

The arbitration of the clock signal is performed each time when the master device releases the SCL pin (the SCL pin is set high) during reception, transmission, or the repeated START state or STOP state.

When the master device releases the SCL pin, the baud-rate generator does not operate.

The pre-set value BRG is written each time the SCL pin is set high while the baud rate generator does not operate. Then, the baud-rate counter starts counting and generates the SCL clock signal.

I2C module interrupts

The I2C module can generate two interrupts by setting the flag bits MI2CIF (IFS0<14> - I2C master interrupt flag) for a master interrupt request and SI2CIF (IFS0<13> - I2C slave interrupt flag) for a slave interrupt request.

An I2C master interrupt request MI2CIF (IFS0<14>) is generated on completion a master message event (transmission or reception). A slave interrupt request SI2CIF (IFS0<13>) is generated when a message intended for a slave device is detected.

Slope control

In the case of the fast mode (400 kHz), the standard I2C communication interface requires the slope control on pins SDA and SCL. The control bit DISSLW allows that, if desired, the slope control is skipped in order to allow baud rates up to 1MHz.

Intelligent peripheral management interface

By setting the control bit IPMIEN the use of the intelligent peripheral management interface (IPMI) support is enabled which allows that the I2C module covers all defined addresses.

General call address support

All devices on the I2C bus are addressed by using the general call address. When the general call address is used, all devices on the I2C bus which receive a message with this address should (at least theoretically) confirm the reception by the ACKNOWLDGE ACK bit. In essence, the general call address is one of the addresses reserved by the I2C protocol. These are usually all '0' with the direction bit R/W=0.

In order to enable the recognition of the general call address, the control bit GCEN (I2CCON<15>) which enables general call address has to be set.