Programming with dsPIC Processors

Overall rating
Introduction of dsPIC Processors

The dsPIC microcontroller is a part of Microchip's 16-Bit microcontroller family. The architecture of dsPIC or Digital Signal Controller is same as the architecture with PIC 16-bit family, with additional blocks of Digital Signal Processing. This power up the standard Microcontroller with powerful mathematical processor required for a Digital Signal Processor. This gives a tremendous amount of functionality into one single chip.

The 16-bit dsPIC30F Digital Signal Controller (DSC) is Microchip’s newest and most advanced processor family. The dsPIC30F is an advanced 16-bit processor that offers true DSP capability with the fundamental real-time control capabilities of a microcontroller. Prioritized interrupts, extensive built-in peripherals and power management features are combined with a full-featured DSP engine.

Dual 40-bit accumulators, single-cycle 16x16 MAC, 40-bit barrel shifter, dual-operand fetches and zero-overhead looping are among the features that make this a very capable DSC.

The dsPIC30F device family employs a powerful 16-bit architecture that seamlessly integrates the control features of a microprocessor (MCU) with the computational capabilities of a digital signal processor (DSP). The resulting functionality is ideal for applications that rely on high-speed, repetitive computations as well as control.

The DSP engine, dual 40-bit accumulators, hardware support for division operations, barrel shifter, 17 x 17 multiplier, a large array of 16-bit working registers and a wide variety of data addressing modes together provide the dsPIC30F CPU with extensive mathematical processing capability. Flexible and deterministic interrupt handling, coupled with a powerful array of peripherals, renders the dsPIC30F devices suitable for control applications.

Reliable, field programmable Flash program memory and data EEPROM ensure scalability of applications that use dsPIC30F devices.

ASSEMBLER Introduction

The assembler is a Windows console application that provides a platform for developing assembly language code. The dsPIC Assembler is a program that translates symbolic code into executable object code. This object code can be executed with a dsPIC-based microcontroller. If you have ever written a computer program directly in machine-recognizable form, such as binary or hexadecimal code, you will appreciate the advantages of programming in symbolic assembly language.

Assembly language operation codes are designed to be easy to remember. You may symbolically express addresses and values referenced in the operand field of instructions. Since you assign these names, you can make them as meaningful as the mnemonics for the instructions.

An assembly program consists of three types of constructs:

  • Machine instructions which are code the machine can execute.
  • Assembler directives which define the program structure and symbols, and generate non-executable code (data, messages, and so on.).
  • Assembler controls which set assembly modes and direct assembly flow.

C C30 Introduction

The C programming language is a general-purpose programming language that provides code efficiency, elements of structured programming, and a rich set of operators. C is not a big language and is not designed for any one particular area of application. Its generality, combined with its absence of restrictions, makes C a convenient and effective programming solution for a wide variety of software tasks.

Many applications can be solved more easily and efficiently with C than with other more specialized languages.

The C30 Compiler is not a universal C compiler adapted for the dsPIC target. It is a ground-up implementation, dedicated to generating extremely fast and compact code for dsPIC microcontrollers. The C30 Compiler provides you with the flexibility of programming in C and the code efficiency and speed of assembly language.

The C language on its own is not capable of performing operations (such as input and output) that would normally require intervention from the operating system. Instead, these capabilities are provided as part of the standard library. Because these functions are separate from the language itself, C is especially suited for producing code that is portable across a wide number of platforms.

MPLAB C30 is an ANSI x3.159-1989-compliant, optimizing C compiler that includes language extensions for dsPIC DSC embedded-control applications.

The compiler is a Windows® console application that provides a platform for developing C code. The compiler is a port of the GCC compiler from the Free Software Foundation.

The MPLAB C Compiler for PIC24 MCUs and dsPIC DSCs compiles C source files, producing assembly language files.

These compiler-generated files are assembled and linked with other object files and libraries to produce the final application program in executable COFF or ELF file format.

The COFF or ELF file can be loaded into the MPLAB IDE, where it can be tested and debugged, or the conversion utility can be used to convert the COFF or ELF file to Intel® hex format, suitable for loading into the command- line simulator or a device programmer.

DsPIC Instruction Set

The dsPIC30F instruction set provides a broad suite of instructions which supports traditional microcontroller applications and a class of instructions which supports math intensive applications. Since almost all of the functionality of the PIC micro instruction set has been maintained, this hybrid instruction set allows a friendly DSP migration path for users already familiar with the PIC micro microcontroller.

The dsPIC30F instruction set has two classes of instructions: MCU instructions and DSP instructions. These two instruction classes are seamlessly integrated into the architecture and are carried out from a single execution unit.

The instruction set includes many addressing modes and was designed for optimum C compiler efficiency. With just a few exceptions, instructions execute in a single cycle.

The exceptions are instructions that change the program flow (BRA, CALL, etc.), the double-word move (MOV.D) instruction and program memory read/write (table) instructions.

For most instructions, the dsPIC30F is capable of executing a data memory read, a working register data read, a data memory write and a program memory (instruction) read, all during one instruction cycle. As a result, three-operand instructions can be supported, allowing A + B = C type operations to be executed in a single cycle.

The dsPIC instruction set has the following key features, some of which are common to other processors, and some of which are not.

The dsPIC30F instruction set contains 94 instructions, which can be grouped into the ten functional Categories,

  • Move Instructions
  • Math Instructions
  • Logic Instructions
  • Rotate / Shift Instructions
  • Bit Instructions
  • Compare / Skip Instructions
  • Flow Instructions
  • Shadow / Stack Instructions
  • Control Instructions
  • DSP Instructions

Most instructions have several different addressing modes and execution flows, which require different instruction variants. For instance, there are six unique ADD instructions and each instruction variant has its own instruction encoding.

Multi-Cycle Instructions

Most instructions execute in a single cycle, with the exception of DO, LNK, MOV.Q, TBLRDH, TBLRDL, TBLWTH, TBLWTL, ULNK and instructions that change the program counter.

These instructions require 2 cycles to execute, with the extra cycle executed as NOP. Skip instructions which skip over a 2-word instruction require 3 instruction cycles to execute, with 2 cycles executed as NOP. The TRAP instruction executes in 4 cycles, which includes exception processing.

Multi-Word Instructions

Almost all instructions consume one instruction word with the exception of the CALL, DO and GOTO instructions. These instructions require two words of memory because their opcodes embed large literal operands.

Addressing Modes

Usually the programs for the dsPIC devices are written in some of the higher programming languages. However, sometimes it is required that a section of the code is written in the assembler. This need is particularly emphasized for the processes involving complex processing.

The optimization is possible in some of the higher programming languages, but it is most efficient when using the assembler, assuming that the architecture of the dsPIC30F devices is known. In these cases the core of the algorithm (most demanding part of the program) is programmed using the assembler.

The basic problem when using the assembler instruction set is data memory access, which could be done in several ways. Each of these has its merits and deficiencies. It is thus very important to know the addressing modes and use them correctly while writing a program.

Each assembler instruction can be divided into two parts. The first part of an instruction is the operation which is carried out (like mov, add, etc.) and the second is the operand(s). The operand is a value undergoing the operation. E.g. the instruction DEC W0, W1 carries out the operation of decrementing, defined by DEC, and the operands are the values in the registers W0 and W1.

Data Addressing Modes

The dsPIC30F supports three native Addressing modes for accessing data memory, along with several forms of immediate addressing.

Data accesses may be performed using file register direct or register indirect addressing, and immediate addressing allows a fixed value to be used by the instruction.

File register addressing provides the ability to operate on data stored in the lower 8K of data memory (Near RAM), and also move data between the working registers and the entire 64K data space. Register direct addressing is used to access the 16 memory mapped working registers, W0:W15.

Register indirect addressing is used to efficiently operate on data stored in the entire 64K data space, using the contents of the working registers as an effective address.

Immediate addressing does not access data memory, but provides the ability to use a constant value as an instruction operand.

File Register Addressing

File register addressing is used by instructions which use a predetermined data address as an operand for the instruction. The majority of instructions that support file register addressing provide access to the lower 8 Kbytes of data memory, which is called the Near RAM. However, the MOV instruction provides access to all 64 Kbytes of memory using file register addressing.

This allows one to load data from any location in data memory to any working register, and store the contents of any working register to any location in data memory.

It should be noted that file register addressing supports both byte and word accesses of data memory, with the exception of the MOV instruction, which accesses all 64K of memory as words.

Register Direct Addressing

Register direct addressing is used to access the contents of the 16 working registers (W0:W15). The Register Direct Addressing mode is fully orthogonal, which allows any working register to be specified for any instruction which uses register direct addressing, and it supports both byte and word accesses.

Instructions which employ register direct addressing use the contents of the specified working register as data to execute the instruction, so this Addressing mode is useful only when data already resides in the working register core.

Register Indirect Addressing

Register indirect addressing is used to access any location in data memory by treating the contents of a working register as an effective address (EA) to data memory.

Essentially, the contents of the working register become a pointer to the location in data memory which is to be accessed by the instruction.

This Addressing mode is powerful, because it also allows one to modify the contents of the working register, either before or after the data access is made, by incrementing or decrementing the EA. By modifying the EA in the same cycle that an operation is being performed, register indirect addressing allows for the efficient processing of data that is stored sequentially in memory.

Direct memory addressing

Direct memory addressing is the mode where the operand is at the memory location specified by the instruction.

This means that the operation is accompanied by the address in the memory where the value undergoing the operation is located.

An example of this mode can be when the task is to take the value located in an address in the memory and transfer it to a general purpose register (W0...W15).


MOV 0x0900, W0.

This defines the operation of moving MOV (Move) while the operands are the value at the address 0x0900 in the data memory and the value kept in the register W0.


The flow of operations is the following:

  • The value in the register W1 is read.
  • The value in the memory location pointed by the register W1 is read,
  • The value read from the memory is written in the register W2.

As already mentioned, indirect register addressing allows processing several data, sequentially saved in the memory. This is accomplished by changing automatically the value of the register used for indirect register addressing.

There are four methods of changing the register value in the process of indirect register addressing:

  • pre-increment [++W1],
  • pre-decrement [--W1],
  • post-increment [W1++],
  • Post-decrement [W1--].

In the pre-increment and pre-decrement addressing modes the value of the register is changed (increased or decreased) first and then the operand address is read.

In the post-increment and post-decrement addressing modes the value of the register is read first and then changed.

In this way the register values are increased or decreased in two steps. The reason that there are two steps is because 16-bit words are in question.

Of course, it is possible to read only one byte, but it should be specified that an 8-bit operation is being executed. Otherwise, 16-bit operation is understood.


MOV $0900, W1

MOV #0, W2


MOV W2, [W1++]

This example writes zeros to six sequential locations in memory.

The instruction REPEAT has the consequence that the subsequent operation is executed the specified number of times plus one, i.e. MOV W2, [W1++] will be executed six times.


All operations are 16-bit, unless specified otherwise. This means that one memory location contains two bytes. Even if the operation was 8-bit, the value of the register would be incremented by two, not by one.

Literal addressing

Literal addressing is the addressing mode where the operand is located immediately after the operation. It is not required to read any register or memory location. The operand is carried together with the operation code as a constant to be used during the execution of the instruction.

The size of the constant depends on the operation to be executed.

The constant can be signed or unsigned and can be saved with a different number of bits. It is customary to specify the limitations in one of the following ways:

  • #lit4 specifies a 4-bit unsigned constant. This means that the range of values of the constant is 0...15. The last number denotes the number of bits and Lit denotes that the constant has no sign.
  • #bit4 specifies a 4-bit unsigned constant. The difference between #lit4 and #bit4 is that #bit4 denotes bit position within a word. It is used in the instructions setting certain bit to logic zero or logic one (BCLR, BSET, BTG…).
  • #Slit4 specifies a signed 4-bit constant. The range of #Slit4 is from –8 to +7.

These are the assembler instructions which are very seldom used if the programming is performed in a higher level language, but it is of considerable importance to know the limitations in order to use correctly certain instructions of the higher level languages.

E.g. shift operand (instructions ASR, LSR, SL) can be done within the range 0-16, which is logical since the 16-bit data are involved.


ADD W1, #4, W2

In the example the value of the register W1 is added 4 and the result is written into W2. For the second operand the literal addressing is used. From the table it can be seen that with the instruction ADD one can use constants within the range 0...31.


Individual instructions can use different ranges. E.g. the instruction ADD has three forms for literal addressing. This should be taken care of only while writing a part of the program using the assembler. When using higher programming languages (PASCAL, C, BASIC), the compiler takes care of the form that should be allocated to a given instruction.

Register Indirect Addressing and Instruction Set

The Addressing modes demonstrate the Indirect Addressing mode capability of the dsPIC30F. Due to operation encoding and functional considerations, not every instruction which supports indirect addressing supports all modes. The majority of instructions which use indirect addressing support the No Modify, Pre-Increment, Pre-Decrement, Post-Increment and Post-Decrement Addressing modes. The MOV instructions, and several accumulator based DSP instructions, are also capable of using the Register Offset Addressing mode.

Modulo and Bit-Reversed Addressing Modes

The dsPIC30F provides support for two special Register Indirect Addressing modes, which are commonly used to implement DSP algorithms. Modulo (or circular) addressing provides an automated means to support circular data buffers in X and/or Y memory.

Modulo buffers remove the need for software to perform address boundary checks, which can improve the performance of certain algorithms. Similarly, Bit-Reversed addressing allows one to access the elements of a buffer in a non-linear fashion. This Addressing mode simplifies data re-ordering for radix-2 FFT algorithms and provides a significant reduction in FFT processing time.

Immediate Addressing

In immediate addressing, the instruction encoding contains a predefined constant operand, which is used by the instruction. This Addressing mode may be used independently, but it is more frequently combined with the File Register, Direct and Indirect Addressing modes. The size of the immediate operand which may be used varies with the instruction type. Constants of size 1-bit (#lit1), 4-bit (#bit4, #lit4 and #Slit4), 5-bit (#lit5), 6-bit (#Slit6), 8-bit (#lit8), 10-bit (#lit10 and #Slit10), 14-bit (#lit14) and 16-bit (#lit16) may be used.

Constants may be signed or unsigned and the symbols #Slit4, #Slit6 and #Slit10 designate a signed constant. All other immediate constants are unsigned. Table 4-4 shows the usage of each immediate operand in the instruction set.

Program Addressing Modes

The dsPIC30F has a 23-bit Program Counter (PC). The PC addresses the 24-bit wide program memory to fetch instructions for execution, and it may be loaded in several ways.

For byte compatibility with the Read and Write instructions, each instruction word consumes two locations in program memory. This means that during serial execution, the PC is loaded with PC+2.

Several methods may be used to modify the PC in a non-sequential manner, and both absolute and relative changes may be made to the PC.

The change to the PC may be from an immediate value encoded in the instruction, or a dynamic value contained in a working register.

When DO looping is active, the PC is loaded with the address stored in the DOSTART register, after the instruction at the DOEND address is executed.

For exception handling, the PC is loaded with the address of the exception handler, which is stored in the interrupt vector table. When required, the software stack is used to return scope to the foreground process from where the change in program flow occurred.

Byte Operations

Since the dsPIC30F data memory is byte addressable, most of the base instructions may operate in either Byte mode or Word mode. When these instructions operate in Byte mode, the following rules apply:

  • all direct working register references use the Least Significant Byte of the 16-bit working register and leave the Most Significant Byte unchanged
  • All indirect working register references use the data byte specified by the 16-bit address stored in the working register.
  • All file register references use the data byte specified by the byte address.
  • The Status Register is updated to reflect the result of the byte operation.

It should be noted that data addresses are always represented as byte addresses. Additionally, the native data format is little-endian, which means that words are stored with the Least Significant Byte at the lower address, and the Most Significant Byte at the adjacent, higher Address.

DSP Engine

The DSP engine features a high speed, 17-bit by 17-bit multiplier, a 40-bit ALU, two 40-bit saturating accumulators and a 40-bit bi-directional barrel shifter. The barrel shifter is capable of shifting a 40-bit value, up to 16-bits right, or up to 16-bits left, in a single cycle.

The DSP instructions operate seamlessly with all other instructions and have been designed for optimal real-time performance. The MAC instruction and other associated instructions can concurrently fetch two data operands from memory while multiplying two working registers. This requires that the data space be split for these instructions and linear for all others. This is achieved in a transparent and flexible manner through dedicating certain working registers to each address space.

The dsPIC30F has a vectored exception scheme with up to 8 sources of non mask able traps and 54 interrupt sources. Each interrupt source can be assigned to one of seven priority levels.

Working Register Array

The 16 working (W) registers can function as data, address or offset registers. The function of a W register is determined by the instruction that accesses it. Byte instructions, which target the working register array, only affect the Least Significant Byte of the target register.

Since the working registers are memory mapped, the least and Most Significant Bytes can be manipulated through byte wide data memory space accesses.

Default Working Register (WREG)

The dsPIC30F instruction set can be divided into two instruction types: working register instructions and file register instructions. The working register instructions use the working register array as data values, or as addresses that point to a memory location.

In contrast, file register instructions operate on a specific memory address contained in the instruction opcodes.

File register instructions that also utilize a working register do not specify the working register that is to be used for the instruction. Instead, a default working register (WREG) is used for these file register instructions.

Working register W0 is assigned to be the WREG. The WREG assignment is not programmable.

Join the World's Largest Technical Community

we respect your privacy.