Chapter13: Examples
- Example 1 – Operating alpha-numeric LCD module by using 4-bit interface
- Example 2 – Operating alpha-numeric LCD module by using 8-bit interface
- Example 3 – Operating a graphical alpha-numeric LCD module (GLCD)
- Example 4 – Operating an AD converter
- Example 5 – Operating a 4 x 4 keyboard
- Example 6 – Realization of pulse width modulation
- Example 7 – Operating a compact flash memory card
- Example 8 – Operating UART modules
- Example 9 – Operating SPI modules
- Example 10 – Operating Secure Digital memory cards
- Example 11 – Operating I2C modules
- Example 12 – Operating a PS/2 keyboard
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.
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.
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.
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.
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.
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.
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.
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.
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.
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);
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.
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.
