Chapter13: Examples

Example 1 – Operating alpha-numeric LCD module by using 4-bit interface

The example shows the connection of an alpha-numeric LCD module 2x16 characters to a dsPIC30F microcontroller by using a 4-bit interface. The following code demonstrates usage of the LCD Custom Library routines. The example covers the initialization of the LCD module and instructions for contolling and writing the module. The realization is carried out by using the mikroPascal compiler for dsPIC30F microcontrollers. The interconnection of the LCD module and a dsPIC30F device by using a 4-bit interface is shown in Fig. 13-1.

Interconnection of the LCD module and a dsPIC30F device by using a 4-bit interface

Fig. 13-1 Interconnection of the LCD module and a dsPIC30F device by using a 4-bit interface

program LCD4bitTest;

var txt : string[15];

begin
  ADPCFG := $FFFF;
  Lcd_Init(PORTB, 3,2,1,0, PORTD, 0,2,1);
  Lcd_Cmd(LCD_CURSOR_OFF);
  Lcd_Cmd(LCD_CLEAR);

  Lcd_Out(1, 1, 'mikroElektronika');
  Lcd_Out(2, 1, '2x16 LCD Testing');
end.

Example 2 – Operating alpha-numeric LCD module by using 8-bit interface

The example shows the connection of an alpha-numeric LCD module 2x16 characters to a dsPIC30F microcontroller by using an 8-bit interface. The following code demonstrates usage of the LCD 8-bit Library routines. The example covers the initialization of the LCD module and instructions for contolling and writing the module. The realization is carried out by using the mikroPascal compiler for dsPIC30F microcontrollers. The interconnection of the LCD module and a dsPIC30F device by using an 8-bit interface is shown in Fig. 13-2.

Interconnection of the LCD module and a dsPIC30F device by using a 8-bit interface

Fig. 13-2 Interconnection of the LCD module and a dsPIC30F device by using a 8-bit interface

program LCD8bitTest;

var txt : string[10];

begin
  ADPCFG := $FFFF; // PORTB to be digital
  Lcd8_Init(PORTB, 7, 6, 5, 4, 3, 2, 1, 0, PORTD, 0, 1, 2);
  Lcd8_Cmd(LCD_CURSOR_OFF);
  Lcd8_Cmd(LCD_CLEAR);

  Lcd8_Out(1, 1, 'mikroElektronika');
  Lcd8_Out(2, 1, '2x16 LCD Testing');
end.

Example 3 – Operating a graphical alpha-numeric LCD module (GLCD)

The example shows the connection of a «dot-matrix» graphical alpha-numeric LCD module (GLCD) to a dsPIC30F microcontroller. The example covers the initialization of the GLCD, writing text, drawing lines, boxes, and circles. The realization is carried out by using the mikroPascal compiler for dsPIC30F microcontrollers. The interconnection of the GLCD module and a dsPIC30F device is shown in Fig. 13-3.

Interconnection of the GLCD module and a dsPIC30F device

Fig. 13-3 Interconnection of the GLCD module and a dsPIC30F device.

program GlcdDemo;

uses __Lib_Glcd_Images;

var ii : byte;
    jj : word;
    someText : array[20] of char;

procedure Delay2S;
begin
  Delay_ms(2000);
end;

begin
  ADPCFG := $FFFF;
  
  Glcd_Init(PORTB, 2, PORTB,3, PORTB,4, PORTB,5, PORTB,7, PORTB,6, PORTD);
  Glcd_Fill(0xAA);
  Delay2S();

  // Main loop
  while TRUE do
  begin

    Glcd_Fill(0x00);  // Clear screen

    // Draw image
    Glcd_Image(truck_bmp);
    Delay2S();

    Glcd_Fill(0x00);  // Clear screen

    // Draw dots
    for jj := 0 to 40 do
    begin
      Glcd_Dot(jj, jj, 1);
    end;

    Delay2S();

    // Draw lines
    Glcd_Fill(0x00);
    Glcd_Line(120, 1, 5, 60, 1);
    Delay2S();
    Glcd_Line(12, 42, 5, 60, 1);

    Delay2S();

    Glcd_H_Line(5, 15, 6, 1);
    Glcd_V_Line(6, 15, 15, 1);

    // Draw rectangle
    Glcd_Rectangle(12, 20, 93,57, 1);

    Delay2S();

    // Draw lines
    Glcd_Line(120, 12, 12,60, 1);

    Delay2S();

    Glcd_H_Line(5, 15, 6, 1);
    Glcd_Line(0, 12, 120, 60, 1);
    Glcd_V_Line(7, 63, 127, 1);

    Delay2S();

    // Draw circles
    for ii := 1 to 10 do
      Glcd_Circle(63, 31, 3*ii, 1);

    Delay2S();

    // Draw box
    Glcd_Box(12, 20, 70, 57, 2);

    Delay2S();

    Glcd_Fill(0x00);

    // Font demo
    Glcd_Set_Font(@System3x6, 3, 6, 32);
    someText := 'SMALL FONT: 3X6';
    Glcd_Write_Text(someText, 20, 5, 1);

    Glcd_Set_Font(@FontSystem5x8, 5, 8, 32);
    someText := 'Large Font 5x8';
    Glcd_Write_Text(someText, 3, 4, 1);

    Delay2S();
  end; //while
end.

Example 4 – Operating an AD converter

The example shows sampling by an AD converter and sends it as a text via UART1. The realization is carried out by using the mikroPascal compiler for dsPIC30F microcontrollers. Fig. 13-4 shows the connection of a dsPIC30F6014A microcontroller for sampling the voltages of the sliding contact of a potentiometer connected to the pin AN10 and sending it as a text via UART1.

Connection of a dsPIC30F6014A device in order to sample on pin AN10

Fig. 13-4 Connection of a dsPIC30F6014A device in order to sample on pin AN10

program ADC_test;

var adcRes : word;
    txt    : string[5];

begin
  TRISB.10 := 1; // set pin as input - needed for ADC to work

  Uart1_Init(9600);

  while TRUE do
    begin
      adcRes := Adc_Read(10);
      WordToStr(adcRes, txt);
      Uart1_Write_Text(txt);
      Delay_ms(50);
    end;
end.

Example 5 – Operating a 4 x 4 keyboard

The example shows the connection of a 4 x 4 keyboard to a dsPIC30F6014A microcontroller. The example shows decoding the keyboard [0...15] to obtain ASCII symbols [0...9,A...F]. Also shown is a counter of the pressed keys. The value of the counter is written in the second line of an LCD module. The realization is carried out by using the mikroPascal compiler for dsPIC30F microcontrollers. Fig. 13-5 shows the interconnection of the keyboard and a dsPIC30F6014A microcontroller.

Interconnection of the keyboard and a dsPIC30F6014A microcontroller

Fig. 13-5 Interconnection of the keyboard and a dsPIC30F6014A microcontroller

program Keypad_4x4_test;

var kp, oldkp  : byte;
    cnt : word;
    txt : string[6];

begin
  cnt := 0;
  Keypad_Init(PORTF);

  ADPCFG := ;
  Glcd_Init_DsPicPro3();
  Glcd_Fill(0x00);
  Glcd_Set_Font(@FontSystem5x8, 5, 8, 32);
  Glcd_Write_Text('Keypad 4x4 example', 10, 0, 1);
  Glcd_Write_Text('Key pressed :', 10, 3, 1);
  Glcd_Write_Text('Times :'      , 10, 6, 1);

  oldkp := 1;

  while TRUE do
  begin
    nop;
    kp := 0;
    // Wait for key to be pressed
    while kp = 0 do
      kp := Keypad_Key_Click();

    if oldkp = kp then
      Inc(cnt)
    else
      cnt := 1;

    oldkp := kp;

    // Prepare value for output
    case kp of
       1: kp := 49;  // 1
       2: kp := 50;  // 2
       3: kp := 51;  // 3
       4: kp := 65;  // A
       5: kp := 52;  // 4
       6: kp := 53;  // 5
       7: kp := 54;  // 6
       8: kp := 66;  // B
       9: kp := 55;  // 7
      10: kp := 56;  // 8
      11: kp := 57;  // 9
      12: kp := 67;  // C
      13: kp := 42;  // *
      14: kp := 48;  // 0
      15: kp := 35;  // #
      16: kp := 68;  // D
    end;

    Glcd_Write_Char(kp, 30, 4, 1);

    if cnt = 65535 then
      cnt := 0;

    // Print on LCD
    WordToStr(cnt, txt);
    Glcd_Write_Text(txt, 10, 7, 1);

  end; //while

end.

Also, an example is given of the clearance by the software of the errors caused by the keyborad bounsing using the same connection as shown in Fig. 13-5. The realization is carried out by using the mikroPascal compiler for dsPIC30F microcontrollers.

program Button_test;

begin
  ADPCFG := $FFFF;
  TRISF := $0000;

  LATF := $AAAA;
  Delay_ms(200);
  LATF := $0000;

  while TRUE do
  begin               // if button on PORTB.0 is logic high for 100ms
    if Button(PORTB, 0, 100, 1) = 1 then
      LATF := $0001
    else
      if Button(PORTB, 1, 100, 1) = 1 then
        LATF := $0002
      else
        if Button(PORTB, 2, 100, 1) = 1 then
          LATF := $0004
        else
          if Button(PORTB, 3, 100, 1) = 1 then
            LATF := $0008
          else LATF := 0;
  end;

end.

Example 6 – Realization of pulse width modulation

The example shows the realization of continuously varying pulse width modulation (PWM). The continously modulated output is on the PORTE.0 pin which is monitored by a LED diode. The realization is carried out by using the mikroPascal compiler for dsPIC30F microcontrollers. Fig. 13-6 shows the electric diagram of the realized continuous PWM of a LED diode connected to PORTE.0.

electric diagram of the realized continuous PWM of a LED diode connected to PORTE.0

Fig. 13-6 The electric diagram of the realized continuous PWM of a LED diode connected to PORTE.0.

program PWM;

var i, duty_50 : word;

begin
  ADPCFG := 0xFFFF;
  TRISE  := 0;
  PORTB  := 0xAAAA;
  TRISB  := 0;
  Delay_ms(1000);

  duty_50 := Pwm_Mc_Init(5000,1,0x01,0);           // Pwm_Mc_Init returns 50% of the duty
  i := duty_50;
  Pwm_Mc_Set_Duty(i, 1);
  Pwm_Mc_Start();

  repeat
    begin
      i := i - 1;
      Pwm_Mc_Set_Duty(i,1);
      Delay_ms(1);
      if (i = 0) then
        i := duty_50 * 2 - 1;                // Do not allow the overflow
      PORTB := i;
    end;
  until false;
end.

Example 7 – Operating a compact flash memory card

The example shows the connection of a compact flash (CF) memory card to a dsPIC30F micocontroller. The CF memory cards are often used as the memory elements in digital video cameras. The memory capacity is high, from 8MB up to 2GB even more, and the read/write time is typically of the order of µs. Application of CF memory cards in microcontroller systems is quite widespread.

In the CF memory cards data are split into sectors (usually of 512 bytes, in earlier models 256 bytes). Reading or writing is not performed directly byte after byte, but data are blocked per sectors through a 512 byte buffer. Fig. 13-7 shows the electrical connection of a CF memory card to a device of the dsPIC30F family. The realization is carried out by using the mikroPascal compiler for dsPIC30F microcontrollers. The example covers, writing and reading one byte from a CF memory card.

Electrical connection of a CF memory card to a device of the dsPIC30F family

Fig. 13-7 Electrical connection of a CF memory card to a device of the dsPIC30F family.

program compact_flash_test;

var
  i : word;
  ddata: array[512] of byte;

//** It is adviceable to initialize dsPIC in one routine. In this way
//**    the code is easier to read and well organized.
procedure Init;
begin
  ADPCFG := 0xFFFF; // portb all digital
  TRISB := 0;       //** make portf to be output
  LATB  := 0;        //** initilize portf

  //** dsPIC30F601x, dsPICPro3
  Cf_Init(PORTG, 0, 1, 2,
          PORTG, 9,
          PORTG, 8,
          PORTG, 7,
          PORTG, 6,
          PORTG, 3,
          PORTD);
  //**

  Uart1_Init(19200);
  //--- CD1 does not work on non-TTL inputs
  //** When CF is inserted CF_Detect will return 1.
  //while CF_Detect = 0 do
  //  begin // do nothing
  //  end;
  //**

  //** Some time is needed for the card to make good contacts
  delay_ms(100);
  //**

end;

procedure WriteByte;
begin
  CF_Write_Init(123, 1);  //** Initialize write to sector 590
  Delay_ms(50);
  i := 0;
  while i < 512 do         //** We will write 512 bytes to CF card
    begin
      Cf_Write_Byte(i);    //** Write one byte
      Inc(i);
    end;
end;

procedure ReadByte;
var tmpRead: word;
begin
  CF_read_Init(123, 1);  //** Initialize read from sector 590
  Delay_ms(50);

  i := 0;
  while i < 512 do        //** We will read 512 bytes from CF card
    begin
      tmpRead := CF_read_Byte;  //** Read one byte
      //Delay_ms(100);
      //LATB := tmpRead;         //** Write readings to PORTF
      Uart1_Write_Char(tmpRead);
      i:=i+1;
    end;
end;

procedure WriteSectors;
begin
  for i := 0 to 511 do
    ddata[i] := i;
  CF_Write_Sector(590, ddata);
  Delay_10ms;
  Uart1_Write_Char('s');
  for i := 0 to 511 do
    ddata[i] := 511-i;
  CF_Write_Sector(591, ddata);
  Uart1_Write_Char('e');
end;//~

procedure ReadSectors;
begin
  CF_Read_Sector(590, ddata);
  for i := 0 to 511 do
    Uart1_Write_Char(ddata[i]);

  Delay_10ms;

  CF_Read_Sector(591, ddata);
  for i := 0 to 511 do
    Uart1_Write_Char(ddata[i]);
end;//~

//** main program starts here
begin
  Init;
  LATB := $AA;
  Delay_ms(500);

  //** first set of tests
  WriteByte;
  LATB := $CC;
  Delay_ms(500);
  ReadByte;
  //**

  //** second set of tests
  WriteSectors;
  LATB := $BB;
  ReadSectors;
  LATB := $FF;       //** Signalize the end of writes
  //**
end.

Example 8 – Operating UART modules

The example shows the initialization, writing, and reading data from the transmitter and receiver of an UART module, respectively. The realization is carried out by using the mikroPascal compiler for dsPIC30F microcontrollers. Fig. 13-8 shows the electrical connection of an UART module to an RS-232 transiever and further connection to the serial port of a PC.

Electrical connection of an UART module to an RS-232 transiever and further connection to the serial port of a PC

Fig. 13-8 Electrical connection of an UART module to an RS-232 transiever and further connection to the serial port of a PC.

program Uart_Test;

var rx1 : word;

begin
  Uart1_Init(9600);

  while TRUE do
  begin
    if Uart1_Data_Ready = 1 then
    begin
      rx1 := Uart1_Read_Char();
      Uart1_Write_Char(rx1);
    end;
  end;

end.

Example 9 – Operating SPI modules

The example shows the initialization, writing, and reading data from the receive and transmit buffer register of an SPI module, respectively. The example shows the connection of the SPI2 module to the serial digital-to-analogue converter (DAC) MCP4921. The realization is carried out by using the mikroPascal compiler for dsPIC30F microcontrollers. Fig. 13-9 shows the electrical connection of the SPI module to the serial DAC MCP4921.

Electrical connection of the SPI module to the serial DAC MCP4921

Fig. 13-9 Electrical connection of the SPI module to the serial DAC MCP4921.

program SPITest;
const  LOAD_PIN      = 2;  // DAC load pin
const  CS_PIN        = 1;  // DAC CS pin

var value : word;

procedure InitMain();
  begin
    TRISC.LOAD_PIN := 0;                   // LOAD pin
    TRISC.CS_PIN   := 0;                   // CS pin
    LATC.CS_PIN    := 1;                   // Set CS to inactive
    LATC.LOAD_PIN  := 0;                   // Set LOAD to inactive
    Spi2_Init_Advanced(_SPI_MASTER, _SPI_16_BIT, _SPI_PRESCALE_SEC_1, _SPI_PRESCALE_PRI_1,
                       _SPI_SS_DISABLE, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_HIGH,
                       _SPI_ACTIVE_2_IDLE);        // Init SPI
  end;

// DAC increments (0..4095) --> output voltage (0..Vref)
procedure DAC_Output(valueDAC : word) ;
  begin
    while (SPI2STAT.1 = 1) do              // wait for SPI module to finish, if doing something
      nop;
    LATC.CS_PIN := 0;                      // CS enable for DAC
    SPI2BUF := 0x3000 or valueDAC;         // Write CurrentValue to DAC (0x3 is required by DAC)
    while (SPI2STAT.1 = 1) do              // Wait for SPI module to finish write
      nop;

    LATC.CS_PIN    := 1;                   // CS disable for DAC
  end;

begin
  InitMain();
  while 1 = 1 do
    begin
      value := 1;
      while value < $FFF do
       begin
         DAC_Output(value);
         Delay_ms(5);
         value := value+1;
       end;
    end;                                    //   the output in the mid-range
end.

Example 10 – Operating Secure Digital memory cards

Secure Digital (SD) is a standard flash memory card based on the earlier Multi Media Card (MMC) standard. Similarly to the CF memory cards, the SD memory cards have a high memory capacity, up to 2GB, and have found the application in the mobile phones, MP3 players, digital cameras, and PDA computers. Access to an SD memory card is realized by using the SPI communication interface.

This example consists of several blocks that demonstrat various aspects of usage of the Mmc_Fat16 library. These are: Creation of new file and writing down to it; Opening existing file and re-writing it (writing from start-of-file); Opening existing file and appending data to it (writing from end-of-file); Opening a file and reading data from it (sending it to USART terminal); Creating and modifying several files at once; Reading file contents; Deleting file(s); Creating the swap file (see Help for details);

Electrical connection of the SD memory card to a device from the dsPIC30F family

Fig. 13-10 Electrical connection of the SD memory card to a device from the dsPIC30F family.

program Mmc_Fat16_Test;


const
  SWAP_FILE_MSG: string[15] = 'Swap file at: ';

var
 fat_txt: string[20];
 file_contents : string[50];

 filename: array[14] of byte;        // File names

 loop, loop2 : word;
 caracter : byte;
 i, size : longint;
 Buffer : array[512] of byte;

procedure Glob_Init;
begin
 fat_txt := 'FAT16 not found';
 file_contents := 'XX MMC/SD FAT16 library by Anton Rieckert' + #10 + #0;
 filename := 'MIKRO00xTXT';          // File names
end;

//M-M-M--------- Creates new file and writes some data to it
procedure M_Create_New_File;
begin
  filename[7] := 'A';
  Mmc_Fat_Assign(filename, 0xA0);       // Will not find file and then create file
  Mmc_Fat_Rewrite();                    // To clear file and start with new data
  for loop := 1 to 99 do                //  We want 5 files on the MMC card
    begin
      Uart1_Write_Char('.');
      file_contents[0] := (loop div 10) + 48;
      file_contents[1] := (loop mod 10) + 48;
//      Uart1_Write_Text(file_contents);
      Mmc_Fat_Write(file_contents, 42);   // write data to the assigned file
    end;
end;//~


//M-M-M--------- Creates many new files and writes data to them
procedure M_Create_Multiple_Files;
begin
  for loop2 := 'B' to 'Z' do
    begin
      Uart1_Write_Char(loop2);              // signal the progress
      filename[7] := loop2;                 // set filename
      Mmc_Fat_Assign(filename, 0xA0);       // find existing file or create a new one
      Mmc_Fat_Rewrite();                    // To clear file and start with new data
      for loop := 1 to 44 do
        begin
          file_contents[0] := (loop div 10) + 48;
          file_contents[1] := (loop mod 10) + 48;
          Mmc_Fat_Write(file_contents, 42);  // write data to the assigned file
        end;
    end;
end;//~


//M-M-M--------- Opens an existing file and rewrites it
procedure M_Open_File_Rewrite;
begin
  filename[7] := 'C';
  Mmc_Fat_Assign(filename, 0);
  Mmc_Fat_Rewrite();
  for loop := 1 to 55 do
    begin
      file_contents[0] := loop div 10 + 64;
      file_contents[1] := loop mod 10 + 64;
      Mmc_Fat_Write(file_contents, 42);    // write data to the assigned file
    end;
end;//~


//M-M-M--------- Opens an existing file and appends data to it
//               (and alters the date/time stamp)
procedure M_Open_File_Append;
begin
  filename[7] := 'B';
  Mmc_Fat_Assign(filename, 0);
  Mmc_Fat_Set_File_Date(2005,6,21,10,35,0);
  Mmc_Fat_Append();                                   // Prepare file for append
  Mmc_Fat_Write(' for mikroElektronika 2005n', 27);   // Write data to assigned file
end;//~


//M-M-M--------- Opens an existing file, reads data from it and puts it to USART
procedure M_Open_File_Read;
begin
  filename[7] := 'B';
  Mmc_Fat_Assign(filename, 0);
  Mmc_Fat_Reset(size);                    // To read file, procedure returns size of file
  for i := 1 to size do
    begin
      Mmc_Fat_Read(caracter);
      Uart1_Write_Char(caracter);         // Write data to USART
    end;
end;//~


//M-M-M--------- Deletes a file. If file doesn't exist, it will first be created
//               and then deleted.
procedure M_Delete_File;
begin
  filename[7] := 'F';
  Mmc_Fat_Assign(filename, 0);
  Mmc_Fat_Delete;
end;//~


//M-M-M--------- Tests whether file exists, and if so sends its creation date
//               and file size via USART
procedure M_Test_File_Exist(fLetter: byte);
var
  fsize: longint;
  year: word;
  month, day, hour, minute: byte;
  outstr: array[12] of byte;
begin
  filename[7] := fLetter;
  if (Mmc_Fat_Assign(filename, 0) <> 0) then
    begin
      //--- file has been found - get its date
      Mmc_Fat_Get_File_Date(year, month, day, hour, minute);
      WordToStr(year, outstr);
      Uart1_Write_Text(outstr);
      WordToStr(month, outstr);
      Uart1_Write_Text(outstr);
      WordToStr(day, outstr);
      Uart1_Write_Text(outstr);
      WordToStr(hour, outstr);
      Uart1_Write_Text(outstr);
      WordToStr(minute, outstr);
      Uart1_Write_Text(outstr);
      //--- get file size
      fsize := Mmc_Fat_Get_File_Size;
      LongIntToStr(longint(fsize), outstr);
      Uart1_Write_Text(outstr);
    end
  else
    begin
      //--- file was not found - signal it
      Uart1_Write_Char(0x55);
      Delay_ms(1000);
      Uart1_Write_Char(0x55);
    end;
end;//~


//-------------- Tries to create a swap file, whose size will be at least 100
//               sectors (see Help for details)
procedure M_Create_Swap_File;
  var i : word;
  begin
    for i:=0 to 511 do
      Buffer[i] := i;

    size := Mmc_Fat_Get_Swap_File(5000, 'mikroE.txt', 0x20); 
    // see help on this function for details

    if (size <> 0) then
      begin
        LongIntToStr(size, fat_txt);
        Uart1_Write_Text(fat_txt);

        for i:=0 to 4999 do
          begin
            Mmc_Write_Sector(size, Buffer);
            Inc(size);
            Uart1_Write_Char('.');
          end;
      end;
  end;//~


begin
//-------------- Main. Uncomment the function(s) to test the desired operation(s)
     Glob_Init;
     //--- prepare PORTD for signalling
     PORTD := 0;
     TRISD := 0;
     ADPCFG := 0xFFFF;
     //--- set up USART for the file read
     Uart1_Init(19200);
     U1MODE.10 := 1;               // clear the way for the SPI
     //--- init the FAT library
     Spi1_Init_Advanced(_SPI_MASTER, _SPI_8_BIT, _SPI_PRESCALE_SEC_1, _SPI_PRESCALE_PRI_64,
     _SPI_SS_DISABLE, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_HIGH, _SPI_ACTIVE_2_IDLE);
     //--- (primary prescale := 64:1), secondary prescale := 1:1

     // use fat16 quick format instead of init routine if a format is needed
     if (Mmc_Fat_Init(PORTB, 8) = 0) then // EasydsPIC3 board
       begin
         // reinitialize spi at higher speed
         Spi1_Init_Advanced(_SPI_MASTER, _SPI_8_BIT, _SPI_PRESCALE_SEC_1, _SPI_PRESCALE_PRI_4,
         _SPI_SS_DISABLE, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_HIGH, _SPI_ACTIVE_2_IDLE);
         //--- Test start
         PORTD := 0x0005;

         //--- Test routines. Uncomment them one-by-one to test certain features
         M_Create_New_File;
         M_Create_Multiple_Files;
         Uart1_Write_Char(10);

         M_Open_File_Rewrite;
         M_Open_File_Append;
         M_Delete_File;
         M_Create_Swap_File;
         Uart1_Write_Char(10);

         M_Open_File_Read;
         Uart1_Write_Char(10);
         M_Test_File_Exist('F');         // this file will not exist here
         Uart1_Write_Char(10);
         M_Test_File_Exist('B');         // this file will exist here
         Uart1_Write_Char(10);
       end
     else
       begin
         Uart1_Write_Text(fat_txt);
       end;
     //--- Test termination
     PORTD := 0xFFFF;

end.//~!

Example 11 – Operating I2C modules

The example shows the initialization, writing, and reading data from the transmit and receive buffer register ofan I2C module, respectively. The example shows the connection of an I2C module to the serial EEPROM memory 24C02. The realization is carried out by using the mikroPascal compiler for dsPIC30F microcontrollers. Fig. 13-11 shows the electrical connection of an I2C module to the EEPROM memory 24C02. The example covers writing to the EEPROM memory, reading data, and data transfer to the PORTF.

Electrical connection of an I2C module to the EEPROM memory 24C02

Fig. 13-11 Electrical connection of an I2C module to the EEPROM memory 24C02.

program I2CEEPROM;

var dAddr : word;
 
begin
  ADPCFG := 0xFFFF;
  PORTB  := 0;
  TRISB  := 0;

  dAddr  := 0x02;

  I2c_Init(0x000186A0);
  I2c_Start();                   // issue I2C start signal
  I2c_Write(0xA2);               // send byte via I2C  (command to 24cO2)
  I2c_Write(dAddr);              // send byte (address of EEPROM location)
  I2c_Write(0xF5);               // send data (data to be written)
  I2c_Stop();

  Delay_ms(100);

  I2c_Start();                   // issue I2C start signal
  I2c_Write(0xA2);               // send byte via I2C  (device address + W)
  I2c_Write(0x02);               // send byte (data address)
  I2c_Restart();                 // issue I2C signal repeated start
  I2c_Write(0xA3);               // send byte (device address + R)
  PORTB := I2c_Read(1);          // Read the data (acknowledge)
  I2c_Stop();
end.

Also, an example is presented showing the connection of a device from the dsPIC30F family to the RTC (Real-Time Clock) generator Philips PCF8583P. The example covers writing to and reading from the RTC generator by using an I2C standard interface. Date and time are printed at LCD.

program RTCWrite;

begin
   ADPCFG := 0xFFFF;
   I2C_Init(10000);         // initialize full master mode
   I2C_Start();             // issue start signal
   I2C_Write(0xA0);         // address PCF8583
   I2C_Write(0);            // start from word at address 0 (configuration word)
   I2C_Write(0x80);         // write $80 to config. (pause counter...)
   I2C_Write(0);            // write 0 to cents word
   I2C_Write(0);            // write 0 to seconds word
   I2C_Write(0x30);         // write $30 to minutes word
   I2C_Write(0x11);         // write $11 to hours word
   I2C_Write(0x24);         // write $24 to year/date word
   I2C_Write(0x08);         // write $08 to weekday/month
   I2C_Stop();              // issue stop signal

   I2C_Start();             // issue start signal
   I2C_Write(0xA0);         // address PCF8530
   I2C_Write(0);            // start from word at address 0
   I2C_Write(0);            // write 0 to config word (enable counting)
   I2C_Stop();              // issue stop signal
end.

program RTCRead;
 
var sec, min1, hr, day, mn, year : byte;
    tnum, txt : array[6] of byte;

procedure Zero_Fill(var value : array[10] of byte);    // fill text repesentation
  begin
    if (value[1] = 0) then
      begin           //      with leading zero
        value[1] := value[0];
        value[0] := 48;
        value[2] := 0;
      end;
  end;
//-------------- Trims the leading spaces from array given with *pt
procedure rtrim(var src, dest : array[10] of byte);
  var i, j : word;
  begin
    i := 0;
    j := 0;
    while (src[i] = ' ') do
      inc(i);
    while (src[i] <> 0) do
      begin
        dest[j] := src[i];
        inc(i);
        inc(j);
      end;
    dest[j] := 0;
  end;
//--------------------- Reads time and date information from RTC (PCF8583)
procedure Read_Time(var sec, min, hr, day, mn, year : byte);
  begin
    I2C_Start();
    I2C_Write(0xA0);
    I2C_Write(2);
    I2c_Restart();
    I2C_Write(0xA1);
    sec := I2c_Read(0);
    min := I2c_Read(0);
    hr  := I2c_Read(0);
    day := I2c_Read(0);
    mn  := I2c_Read(1);
    I2C_Stop();

  end;

//-------------------- Formats date and time
procedure Transform_Time(var sec, min, hr, day, mn, year : byte);
  begin
    sec  :=  ((sec and 0xF0) shr 4)*10 + (sec and 0x0F);
    min  :=  ((min and 0xF0) shr 4)*10 + (min and 0x0F);
    hr   :=  ((hr and 0xF0) shr 4)*10 + (hr and 0x0F);
    year :=  (day and 0xC0) shr 6;
    day  :=  ((day and 0x30) shr 4)*10 + (day and 0x0F);
    mn   :=  ((mn and 0x10) shr 4)*10 + (mn and 0x0F);
  end;

//-------------------- Output values to LCD
procedure Display_Time( sec, min, hr, day, mn, year : byte);
  begin
    WordToStr(word(day), tnum);
    rtrim(tnum, txt);
    Zero_Fill(txt);
    Lcd_Out(1, 6, txt);

    WordToStr(word(mn), tnum);
    rtrim(tnum, txt);
    Zero_Fill(txt);
    Lcd_Out(1,9,txt);
    Lcd_Chr(1,15,52+year);

    WordToStr(word(hr), tnum);
    rtrim(tnum, txt);
    Zero_Fill(txt);
    Lcd_Out(2,6,txt);

    WordToStr(word(min), tnum);
    rtrim(tnum, txt);
    Zero_Fill(txt);
    Lcd_Out(2,9,txt);

    WordToStr(word(sec), tnum);
    rtrim(tnum, txt);
    Zero_Fill(txt);
    Lcd_Out(2,12,txt);
  end;

//------------------ Performs project-wide init
procedure Init_Main();
  begin
    ADPCFG := 0xFFFF;
    TRISD  := 0;                // designate portd as output
    Lcd_Init_EasyDsPIC4();
    I2C_Init(100000);           // initialize I2C
    txt := 'Date:';             // prepare and output static text on LCD
    Lcd_Out(1,1,txt);
    Lcd_Chr(1,8,':');
    Lcd_Chr(1,11,':');
    txt := 'Time:';
    Lcd_Out(2,1,txt);
    Lcd_Chr(2,8,':');
    Lcd_Chr(2,11,':');
    txt := '200';
    Lcd_Out(1,12,txt);
    Lcd_Cmd(LCD_CURSOR_OFF);   // cursor off
  end;
//----------------- Main procedure
begin
  Init_Main();                                       // perform initialization
  while true do
    begin
      Read_Time(sec, min1, hr, day, mn, year);       // read time from RTC(PCF8583)
      Transform_Time(sec, min1, hr, day, mn, year);  // format date and time
      Display_Time(sec, min1, hr, day, mn, year);    // prepare and display on LCD
      Delay_ms(1000);                                // wait 1s
    end;
end.

Example 12 – Operating a PS/2 keyboard

The example shows the connection of a device from the dsPIC30F family to a standard PS/2 keyboard. It is important to note that all pins of the PS/2 keyboard connected to the dsPIC30F device are connected to the power supply by the pull-up resistors. The realization is carried out by using the mikroPascal compiler for dsPIC30F microcontrollers.

program ps2_test;

var
 keydata, special, down : word;
 txt: array[20] of char;
 
begin
  nop;
  ADPCFG:=$FFFF; // PORTB to be digital on 30F4013
  keydata := 0;
  special := 0;
  down    := 0;
  
  Ps2_Config(PORTC, 14, 13);
  Uart1_Init(9600);
  txt := 'You can type now!';
  Uart1_Write_Text(txt);    // Ready

  while true do
  begin
    if Ps2_Key_Read(keydata, special, down)=1 then
      begin
        if (down<>0) and (keydata = 16) then
          begin
            Uart1_Write_Char(0x08);
          end
        else if (down<>0) and (keydata = 13) then
               begin  // Enter
                 Uart1_Write_Char(13);
                 Uart1_Write_Char(10);
               end
             else if (down<>0) and (special=0) and (keydata<>0) then
                    begin
                      Uart1_Write_Char(keydata);
                    end;
      end;
    Delay_ms(1); // debounce
  end;
end.