http://www.opencircuits.com/api.php?action=feedcontributions&user=Yan&feedformat=atomOpenCircuits - User contributions [en]2024-03-29T14:31:40ZUser contributionsMediaWiki 1.34.2http://www.opencircuits.com/index.php?title=Topway_LCD&diff=18627Topway LCD2009-08-26T02:51:48Z<p>Yan: /* LCD model: LM6023ADW */ adding life time</p>
<hr />
<div>==LCD model: LM6023ADW==<br />
*manufacturer : [http://www.topwaydisplay.com/ Topway]<br />
<br />
===Tested temperature Range : -8 to 40===<br />
*The contrast becomes dimmer when Temperature is lower than 5 degree<br />
*The contrast becomes brigher when Temperature is hight than 35 degree<br />
<br />
===life time===<br />
*normal backlight as 40,000hrs, dim down backlight as 90,000hrs<br />
<br />
===5V LCD to 3.3V LCD===<br />
* connect JP3<br />
* disconnect JP2<br />
* place a 4.7uF cap onto C10.<br />
* remove R7. <br />
<br />
===3.3V LCD to 5V LCD===<br />
* disconnect JP3<br />
* connect JP2<br />
* remove C10<br />
* place 20ohm onto R7.</div>Yanhttp://www.opencircuits.com/index.php?title=GPIB&diff=18262GPIB2009-04-21T10:41:44Z<p>Yan: add todo</p>
<hr />
<div>==Introduction==<br />
*http://www.ni.com/gpib/what_is.htm / http://en.wikipedia.org/wiki/IEEE-488<br />
*it is one of a communication standard of most equipments<br />
*A interface(in both hw & sw) to any platforms, such as dspic33 board, bf1 board ...<br />
<br />
==interface==<br />
<br />
===I2C protocol===<br />
*apply as one to many(can be different kind of devices)<br />
*different platforms<br />
**for dspic, sw driver implement in freertos following posix arch.<br />
**for bf1 pf, sw driver implment in uclinux following posix arch.<br />
<br />
==ToDos==<br />
<br />
===adding RS232 Interface===<br />
*reference -- http://sine.ni.com/nips/cds/view/p/lang/en/nid/203553</div>Yanhttp://www.opencircuits.com/index.php?title=Programming_the_Device&diff=17709Programming the Device2009-02-02T10:02:16Z<p>Yan: /* Download Firmware */ more easy to read for the cmd</p>
<hr />
<div>==Requirements==<br />
<br />
===Hardware===<br />
#PC with COM port (Windows XP Installed for MPLAB)<br />
#ICD2 Programmer<br />
#Target Board<br />
#5V Power Supply<br />
<br />
===Software===<br />
#[http://ww1.microchip.com/downloads/en/DeviceDoc/MP750.zip MPLAB IDE v7.50]: v7.60 is not compatible with our current [http://www.sure-electronics.com/ ICD2 Programmers]. There are consistent "Devices cannot be founded" warnings.<br />
#[http://chungyan5.no-ip.org/websvn/listing.php dsPicProgrammer] ('''dsPicProgrammer.jar''')<br />
<br />
===Files===<br />
#[http://chungyan5.no-ip.org/websvn/listing.php dsPicBootloader] ('''bl_5011.hex'''). Original assembly code by ingenia can be downloaded from [http://www.ingenia-cat.com/download/iBL.s here].<br />
#Application hex file (e.g. '''app.hex''')<br />
<br />
<br />
==Loading Bootloader (Once only)==<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Loading Bootloader<br />
! Step !! Remarks <br />
|-valign="top"<br />
| Install [http://ww1.microchip.com/downloads/en/DeviceDoc/MP750.zip MPLAB IDE] || <br />
*Do '''NOT''' connect ICD 2 (via USB) to PC<br />
*Execute '''MPLAB vX.XX Install.exe'''<br />
|-valign="top"<br />
| Install USB Driver ||<br />
*Follow the instruction in (C:\Program Files\Microchip\MPLAB IDE\ICD2\Drivers\Ddicd2.htm)<br />
|-valign="top"<br />
| Select Target Chip ||<br />
*Run MPLAB IDE on PC<br />
*Select: Configure>Select Devices...<br />
*Choose dsPIC30F5011<br />
|-valign="top"<br />
| Target <-> ICD 2 ||<br />
*Use six pin cable. Beware of the pin assignments. Only pin 1 - 5 should be used.<br />
*Place Jumper on target board (if any). The Jumper connects target V<sub>cc</sub> to ICD 2.<br />
*Do '''NOT''' power-up the target.<br />
|-valign="top"<br />
| ICD 2 <-> PC ||<br />
*Plug-in ICD 2 to PC via USB cable<br />
*Power-up the target.<br />
*Select: Programmer>Select Programmer>MPLAB ICD 2<br />
*If this is the first time the ICD 2 is connected to PC, MPLAB IDE will automatically download the required OS to ICD 2, wait until it has finished<br />
*If you have not connected and powered up the target, you might see Warnings on invalid device IDs, and/or running self tests.<br />
*See results of self test if necessary: Programmer>Settings, Status Tab. Refer to [http://ww1.microchip.com/downloads/en/DeviceDoc/51331B.pdf ICD2 User's Guide] Chapter 7.<br />
|-valign="top"<br />
| Load Bootloader ||<br />
*Select: File>Import...<br />
*Select '''bl_5011.hex'''<br />
|-valign="top"<br />
| Start Programming ||<br />
*Select: Programmer>Program<br />
|-valign="top"<br />
| Finishing ||<br />
*Power-down the Taget<br />
*Select: Programmer>Select Programmer>None<br />
*Unplug USB cable<br />
|-<br />
|}<br />
<br />
==Hardware Setting==<br />
[[Image:DSC00921.JPG]]<br />
*Connect your usb to rs232 cable to your computer<br />
*Or Using a real RS232 Port -- COM PORT<br />
<br />
==Download and Loading Firmware==<br />
<br />
===Make sure the RS232 Port in your computer===<br />
[[Image:1.jpg]]<br />
*Go to Control Panel \ Device Manager<br />
<br />
[[Image:2.jpg]]<br />
*Find out your Device comm port Number<br />
<br />
===Get the Dspic Programmer===<br />
*Download [http://chungyan5.no-ip.org/open_data/electronic_computer/platforms/dspic/dsPicProgrammer/dsPicProgrammer1.5.5.zip dsPic_Programmer.zip], [http://chungyan5.no-ip.org/open_data/electronic_computer/platforms/dspic/dsPicProgrammer/ws/ updated directory] or [http://chungyan5.no-ip.org/vc svn server]<br />
*Save to a directory.<br />
::e.g. desktop<br />
*Unzip the dsPic_Programmer.zip, then you have an unziped file.<br />
[[Image:prog_guid_dl.JPG]]<br />
<br />
----<br />
<br />
*Drag the unzip file to a director.<br />
::eg. USB memory devics<br />
[[Image:prog_guid_drag.JPG]]<br />
<br />
----<br />
<br />
*Save your .hex file(foo.hex) to your directory location <br />
::e.g. X:\dsPic_Programmer\ ---> X:\ is the driver where the dsPic_Programmer located<br />
[[Image:prog_guid_hex.JPG]]<br />
<br />
===Download Firmware===<br />
*Start a Command Prompt<br />
**Start -> Run<br>[[Image:2 1 run.JPG]]<br><br />
**Enter cmd<br>[[Image:2 2 cmd.JPG]]<br><br />
*Run dsPicProgrammer<br />
**Make sure your device is connected through a "Direct RS232 Cable" to PC Serial Port. <br />
**Change to the directory where dsPicProgrammer.jar is located and run the command:<br />
***for example, '''jre\bin\java -Djava.library.path=.\rxtx\bin -jar dspicProgrammer.jar COM1 115200 foo.hex'''<br />
***Or directly using '''dsPicProgrammer.bat COM1 115200 foo.hex'''(Windows)<br />
***'''jre\bin\java -jar dsPicProgrammer.jar /dev/ttyS0 115200 foo.hex''' (Linux)<br />
:::where COM1 is your COM Port ID<br />
:::115200 is communication speed [in bps]<br />
:::foo.hex is your firmware new file<br />
::[[Image:5.jpg]]<br />
:*When the program prompt you for an input, press y:<br>[[Image:2 4 prompt.JPG]]<br><br />
:*If communication can be established, you should see something like this:<br>[[Image:2 5 progress.JPG]]<br><br />
:*Wait until programming is completed.<br>[[Image:2 6 complete.JPG]]<br><br />
:*after all completed, power OFF your device, then power ON again, enjoy your new updated.<br />
<br />
==Troubleshooting==<br />
===Invalid COM Port===<br />
*In case of selecting an invalid COM port, you should see the error message:<br>gnu.io.NoSuchPortException: Choosing COM Port Error<br>[[Image:3 1 com err.JPG]]<br><br><br />
===Missing firmware file===<br />
*In case of selecting a firmware file that does not exist, you should see the error message:<br>java.io.FileNotFoundException: foo1.hex <The system cannot find the file specified><br>[[Image:3 2 file err.JPG]]<br><br><br />
===Missing RXTX driver===<br />
*In case of missing the RXTX driver, you should see the error message:<br>Exception in thread “main” java.lang.NoClassDefFoundError: gnu/io/UnsupportedCommOperationException<br>[[Image:3 3 rxtx err.JPG]]<br><br></div>Yanhttp://www.opencircuits.com/index.php?title=Programming_the_Device&diff=17707Programming the Device2009-02-02T08:23:58Z<p>Yan: /* Download and Loading Firmware */ remove the redundance bet. XP & vista</p>
<hr />
<div>==Requirements==<br />
<br />
===Hardware===<br />
#PC with COM port (Windows XP Installed for MPLAB)<br />
#ICD2 Programmer<br />
#Target Board<br />
#5V Power Supply<br />
<br />
===Software===<br />
#[http://ww1.microchip.com/downloads/en/DeviceDoc/MP750.zip MPLAB IDE v7.50]: v7.60 is not compatible with our current [http://www.sure-electronics.com/ ICD2 Programmers]. There are consistent "Devices cannot be founded" warnings.<br />
#[http://chungyan5.no-ip.org/websvn/listing.php dsPicProgrammer] ('''dsPicProgrammer.jar''')<br />
<br />
===Files===<br />
#[http://chungyan5.no-ip.org/websvn/listing.php dsPicBootloader] ('''bl_5011.hex'''). Original assembly code by ingenia can be downloaded from [http://www.ingenia-cat.com/download/iBL.s here].<br />
#Application hex file (e.g. '''app.hex''')<br />
<br />
<br />
==Loading Bootloader (Once only)==<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Loading Bootloader<br />
! Step !! Remarks <br />
|-valign="top"<br />
| Install [http://ww1.microchip.com/downloads/en/DeviceDoc/MP750.zip MPLAB IDE] || <br />
*Do '''NOT''' connect ICD 2 (via USB) to PC<br />
*Execute '''MPLAB vX.XX Install.exe'''<br />
|-valign="top"<br />
| Install USB Driver ||<br />
*Follow the instruction in (C:\Program Files\Microchip\MPLAB IDE\ICD2\Drivers\Ddicd2.htm)<br />
|-valign="top"<br />
| Select Target Chip ||<br />
*Run MPLAB IDE on PC<br />
*Select: Configure>Select Devices...<br />
*Choose dsPIC30F5011<br />
|-valign="top"<br />
| Target <-> ICD 2 ||<br />
*Use six pin cable. Beware of the pin assignments. Only pin 1 - 5 should be used.<br />
*Place Jumper on target board (if any). The Jumper connects target V<sub>cc</sub> to ICD 2.<br />
*Do '''NOT''' power-up the target.<br />
|-valign="top"<br />
| ICD 2 <-> PC ||<br />
*Plug-in ICD 2 to PC via USB cable<br />
*Power-up the target.<br />
*Select: Programmer>Select Programmer>MPLAB ICD 2<br />
*If this is the first time the ICD 2 is connected to PC, MPLAB IDE will automatically download the required OS to ICD 2, wait until it has finished<br />
*If you have not connected and powered up the target, you might see Warnings on invalid device IDs, and/or running self tests.<br />
*See results of self test if necessary: Programmer>Settings, Status Tab. Refer to [http://ww1.microchip.com/downloads/en/DeviceDoc/51331B.pdf ICD2 User's Guide] Chapter 7.<br />
|-valign="top"<br />
| Load Bootloader ||<br />
*Select: File>Import...<br />
*Select '''bl_5011.hex'''<br />
|-valign="top"<br />
| Start Programming ||<br />
*Select: Programmer>Program<br />
|-valign="top"<br />
| Finishing ||<br />
*Power-down the Taget<br />
*Select: Programmer>Select Programmer>None<br />
*Unplug USB cable<br />
|-<br />
|}<br />
<br />
==Hardware Setting==<br />
[[Image:DSC00921.JPG]]<br />
*Connect your usb to rs232 cable to your computer<br />
*Or Using a real RS232 Port -- COM PORT<br />
<br />
==Download and Loading Firmware==<br />
<br />
===Make sure the RS232 Port in your computer===<br />
[[Image:1.jpg]]<br />
*Go to Control Panel \ Device Manager<br />
<br />
[[Image:2.jpg]]<br />
*Find out your Device comm port Number<br />
<br />
===Get the Dspic Programmer===<br />
*Download [http://chungyan5.no-ip.org/open_data/electronic_computer/platforms/dspic/dsPicProgrammer/dsPicProgrammer1.5.5.zip dsPic_Programmer.zip], [http://chungyan5.no-ip.org/open_data/electronic_computer/platforms/dspic/dsPicProgrammer/ws/ updated directory] or [http://chungyan5.no-ip.org/vc svn server]<br />
*Save to a directory.<br />
::e.g. desktop<br />
*Unzip the dsPic_Programmer.zip, then you have an unziped file.<br />
[[Image:prog_guid_dl.JPG]]<br />
<br />
----<br />
<br />
*Drag the unzip file to a director.<br />
::eg. USB memory devics<br />
[[Image:prog_guid_drag.JPG]]<br />
<br />
----<br />
<br />
*Save your .hex file(foo.hex) to your directory location <br />
::e.g. X:\dsPic_Programmer\ ---> X:\ is the driver where the dsPic_Programmer located<br />
[[Image:prog_guid_hex.JPG]]<br />
<br />
===Download Firmware===<br />
*Start a Command Prompt<br />
**Start -> Run<br>[[Image:2 1 run.JPG]]<br><br />
**Enter cmd<br>[[Image:2 2 cmd.JPG]]<br><br />
*Run dsPicProgrammer<br />
**Make sure your device is connected through a "Direct RS232 Cable" to PC Serial Port. <br />
**Change to the directory where dsPicProgrammer.jar is located and run the command:<br />
***for example, jre\bin\java -Djava.library.path=.\rxtx\bin -jar dspicProgrammer.jar COM1 115200 foo.hex<br />
***Or directly using dsPicProgrammer.bat COM1 115200 foo.hex(Windows)<br />
***java -jar dsPicProgrammer.jar /dev/ttyS0 115200 foo.hex (Linux)<br />
:::where COM1 is your COM Port ID<br />
:::115200 is communication speed [in bps]<br />
:::foo.hex is your firmware new file<br />
::[[Image:2 3 command.JPG]]<br />
:*When the program prompt you for an input, press y:<br>[[Image:2 4 prompt.JPG]]<br><br />
:*If communication can be established, you should see something like this:<br>[[Image:2 5 progress.JPG]]<br><br />
:*Wait until programming is completed.<br>[[Image:2 6 complete.JPG]]<br><br />
:*after all completed, power OFF your device, then power ON again, enjoy your new updated.<br />
<br />
==Troubleshooting==<br />
===Invalid COM Port===<br />
*In case of selecting an invalid COM port, you should see the error message:<br>gnu.io.NoSuchPortException: Choosing COM Port Error<br>[[Image:3 1 com err.JPG]]<br><br><br />
===Missing firmware file===<br />
*In case of selecting a firmware file that does not exist, you should see the error message:<br>java.io.FileNotFoundException: foo1.hex <The system cannot find the file specified><br>[[Image:3 2 file err.JPG]]<br><br><br />
===Missing RXTX driver===<br />
*In case of missing the RXTX driver, you should see the error message:<br>Exception in thread “main” java.lang.NoClassDefFoundError: gnu/io/UnsupportedCommOperationException<br>[[Image:3 3 rxtx err.JPG]]<br><br></div>Yanhttp://www.opencircuits.com/index.php?title=Programming_the_Device&diff=17706Programming the Device2009-02-02T07:56:12Z<p>Yan: /* Hardware Setting */ Using a real RS232 Port</p>
<hr />
<div>==Requirements==<br />
<br />
===Hardware===<br />
#PC with COM port (Windows XP Installed for MPLAB)<br />
#ICD2 Programmer<br />
#Target Board<br />
#5V Power Supply<br />
<br />
===Software===<br />
#[http://ww1.microchip.com/downloads/en/DeviceDoc/MP750.zip MPLAB IDE v7.50]: v7.60 is not compatible with our current [http://www.sure-electronics.com/ ICD2 Programmers]. There are consistent "Devices cannot be founded" warnings.<br />
#[http://chungyan5.no-ip.org/websvn/listing.php dsPicProgrammer] ('''dsPicProgrammer.jar''')<br />
<br />
===Files===<br />
#[http://chungyan5.no-ip.org/websvn/listing.php dsPicBootloader] ('''bl_5011.hex'''). Original assembly code by ingenia can be downloaded from [http://www.ingenia-cat.com/download/iBL.s here].<br />
#Application hex file (e.g. '''app.hex''')<br />
<br />
<br />
==Loading Bootloader (Once only)==<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Loading Bootloader<br />
! Step !! Remarks <br />
|-valign="top"<br />
| Install [http://ww1.microchip.com/downloads/en/DeviceDoc/MP750.zip MPLAB IDE] || <br />
*Do '''NOT''' connect ICD 2 (via USB) to PC<br />
*Execute '''MPLAB vX.XX Install.exe'''<br />
|-valign="top"<br />
| Install USB Driver ||<br />
*Follow the instruction in (C:\Program Files\Microchip\MPLAB IDE\ICD2\Drivers\Ddicd2.htm)<br />
|-valign="top"<br />
| Select Target Chip ||<br />
*Run MPLAB IDE on PC<br />
*Select: Configure>Select Devices...<br />
*Choose dsPIC30F5011<br />
|-valign="top"<br />
| Target <-> ICD 2 ||<br />
*Use six pin cable. Beware of the pin assignments. Only pin 1 - 5 should be used.<br />
*Place Jumper on target board (if any). The Jumper connects target V<sub>cc</sub> to ICD 2.<br />
*Do '''NOT''' power-up the target.<br />
|-valign="top"<br />
| ICD 2 <-> PC ||<br />
*Plug-in ICD 2 to PC via USB cable<br />
*Power-up the target.<br />
*Select: Programmer>Select Programmer>MPLAB ICD 2<br />
*If this is the first time the ICD 2 is connected to PC, MPLAB IDE will automatically download the required OS to ICD 2, wait until it has finished<br />
*If you have not connected and powered up the target, you might see Warnings on invalid device IDs, and/or running self tests.<br />
*See results of self test if necessary: Programmer>Settings, Status Tab. Refer to [http://ww1.microchip.com/downloads/en/DeviceDoc/51331B.pdf ICD2 User's Guide] Chapter 7.<br />
|-valign="top"<br />
| Load Bootloader ||<br />
*Select: File>Import...<br />
*Select '''bl_5011.hex'''<br />
|-valign="top"<br />
| Start Programming ||<br />
*Select: Programmer>Program<br />
|-valign="top"<br />
| Finishing ||<br />
*Power-down the Taget<br />
*Select: Programmer>Select Programmer>None<br />
*Unplug USB cable<br />
|-<br />
|}<br />
<br />
==Hardware Setting==<br />
[[Image:DSC00921.JPG]]<br />
*Connect your usb to rs232 cable to your computer<br />
*Or Using a real RS232 Port -- COM PORT<br />
<br />
==Download and Loading Firmware==<br />
===Windows Vista===<br />
[[Image:1.jpg]]<br />
*Go to Control Panel \ Device Manager<br />
<br />
[[Image:2.jpg]]<br />
*Find out your Device comm port Number<br />
<br />
[[Image:3.jpg]]<br />
*Open a command prompt<br />
<br />
[[Image:4.jpg]]<br />
*Run dsPicProgrammer<br />
**Input cd Desktop\dsPic_production\dsPicProgrammer<br />
<br />
[[Image:5.jpg]]<br />
*Loading Firmware<br />
**Input jre\bin\java -Djava.library.path=.\rxtx\bin -jar dspicProgrammer.jar COM1 115200 ./firmware/foo.hex<br />
**eg. jre\bin\java -Djava.library.path=.\rxtx\bin -jar dspicProgrammer.jar COM9 115200 ./firmware/8072303.hex<br />
:::where COM9 is your COM Port ID<br />
:::115200 is communication speed [in bps]<br />
:::foo.hex is your firmware new file<br />
<br />
[[Image:6.jpg]]<br />
*Enter Y to comfirm<br />
<br />
[[Image:2 6 complete.JPG]]<br />
:*Wait until programming is completed.<br />
:*after all completed, power OFF your device, then power ON again, enjoy your new updated.<br />
<br />
<br />
<br />
===Windows XP===<br />
*If the RS232 converter hardware required, pls go there [[RS232_RS485_USB_Converter_Board]] for RS232 converter only<br />
*Download [http://chungyan5.no-ip.org/open_data/electronic_computer/platforms/dspic/dsPicProgrammer/dsPicProgrammer1.5.5.zip dsPic_Programmer.zip], [http://chungyan5.no-ip.org/open_data/electronic_computer/platforms/dspic/dsPicProgrammer/ws/ updated directory] or [http://chungyan5.no-ip.org/vc svn server]<br />
*Save to a directory.<br />
::e.g. desktop<br />
*Unzip the dsPic_Programmer.zip, then you have an unziped file.<br />
[[Image:prog_guid_dl.JPG]]<br />
<br />
----<br />
<br />
*Drag the unzip file to a director.<br />
::eg. USB memory devics<br />
[[Image:prog_guid_drag.JPG]]<br />
<br />
----<br />
<br />
*Save your .hex file(foo.hex) to your directory location <br />
::e.g. X:\dsPic_Programmer\ ---> X:\ is the driver where the dsPic_Programmer located<br />
[[Image:prog_guid_hex.JPG]]<br />
===Download Firmware===<br />
*Start a Command Prompt<br />
**Start -> Run<br>[[Image:2 1 run.JPG]]<br><br />
**Enter cmd<br>[[Image:2 2 cmd.JPG]]<br><br />
*Run dsPicProgrammer<br />
**Make sure your device is connected through a "Direct RS232 Cable" to PC Serial Port. <br />
**Change to the directory where dsPicProgrammer.jar is located and run the command:<br />
***for example, jre\bin\java -Djava.library.path=.\rxtx\bin -jar dspicProgrammer.jar COM1 115200 foo.hex<br />
***Or directly using dsPicProgrammer.bat COM1 115200 foo.hex(Windows)<br />
***java -jar dsPicProgrammer.jar /dev/ttyS0 115200 foo.hex (Linux)<br />
:::where COM1 is your COM Port ID<br />
:::115200 is communication speed [in bps]<br />
:::foo.hex is your firmware new file<br />
::[[Image:2 3 command.JPG]]<br />
:*When the program prompt you for an input, press y:<br>[[Image:2 4 prompt.JPG]]<br><br />
:*If communication can be established, you should see something like this:<br>[[Image:2 5 progress.JPG]]<br><br />
:*Wait until programming is completed.<br>[[Image:2 6 complete.JPG]]<br><br />
:*after all completed, power OFF your device, then power ON again, enjoy your new updated.<br />
<br />
==Troubleshooting==<br />
===Invalid COM Port===<br />
*In case of selecting an invalid COM port, you should see the error message:<br>gnu.io.NoSuchPortException: Choosing COM Port Error<br>[[Image:3 1 com err.JPG]]<br><br><br />
===Missing firmware file===<br />
*In case of selecting a firmware file that does not exist, you should see the error message:<br>java.io.FileNotFoundException: foo1.hex <The system cannot find the file specified><br>[[Image:3 2 file err.JPG]]<br><br><br />
===Missing RXTX driver===<br />
*In case of missing the RXTX driver, you should see the error message:<br>Exception in thread “main” java.lang.NoClassDefFoundError: gnu/io/UnsupportedCommOperationException<br>[[Image:3 3 rxtx err.JPG]]<br><br></div>Yanhttp://www.opencircuits.com/index.php?title=Optoelectronics&diff=17161Optoelectronics2008-12-31T07:32:25Z<p>Yan: /* LCDs */</p>
<hr />
<div>Optoelectronics are devices that are some combination of electrical and optical. Perhaps the simplest is the Light Emitting Diode or LED which converts electrical energy into light. A listing of some optoelectronic devices follows.<br />
<br />
<br />
== LEDs ==<br />
LEDs are diodes designed to produce visible light.<br />
<br />
Commonly a small low power device that makes a not too bright light. High power, high brightness versions are now becoming widely available. The low power ones typically run on a volt or so, at about 10 ma. Typically they are run on higher voltages with a current limiting resistor that sets the current. Current control is almost always required ( often with a resistor ) as LED are very sensitive to small voltage changes. Like other diodes they conduct only in one direction.<br />
<br />
When using a LED in a cicuit it's important to use a current limiter such as a resistor. When using resistors measure the foreward voltage drop of the LED with a multimeter, subtract this from the supply voltage, then plug the difference into ohms law to calculate the required resistor value. Different color LEDs all have different voltage drops.<br />
<br />
Uses<br />
*Indicator<br />
*Part of 7 segment display<br />
*Light source<br />
<br />
External Links<br />
<br />
# [http://en.wikipedia.org/wiki/Light_Emitting_Diode Light-emitting diode From Wikipedia, the free encyclopedia]<br />
# [http://www.iguanalabs.com/1stled.htm Learning About Transistors and LEDs]<br />
# [http://www.piclist.com/techref/io/led/pulse.htm?key=base+resistor&from= Brighter Appearance through pulsing]<br />
# [http://www.uchobby.com/index.php/2008/02/25/improving-the-ping-pong-ball-led-diffuser/ Improving the Ping Pong Ball LED Diffuser ]<br />
# [[Basic_Circuits_and_Circuit_Building_Blocks#Light_Emitting_Diode_.28_with_current_limiting_resistor_.29 ]]<br />
<br />
== LCDs ==<br />
<br />
Liquid Crystal Displays<br />
* Serial - These displays have a microcontroller on the display with a serial or I2C connection. Several builtin fonts are typically included. These displays are very easy to use, but the update rate for a display is very slow. Fullblown bitmap support is usually not available. Typical price for these displays is $50+.<br />
<br />
* Parallel - Parallel displays connect to a microcontroller via a parallel interface( the bitwidth varies from 8bits to 32bits ). Displays can have a much faster update rate then serial since they allow arbitrary graphs to be display. The displays are typically much cheaper then serial display starting as low as $20.<br />
<br />
Finding LCD displays is not easy since huge distributors such as Digikey have a limited selection. <br />
<br />
Some places that do have LCDs for hobby use:<br />
<br />
* [http://www.sparkfun.com Sparkfun] - Has a good selection of both parallel and serial displays. <br />
* [http://www.matrixorbital.com MatrixOrbital] - Specializes in serial display especially the type for direct connection to a PC.<br />
* [http://www.jameco.com Jameco] - A small selection. Mostly serial.<br />
* [http://www.seeedstudio.com/depot Seeedstudio] - Free sourcing services with some stock of basic LCD.<br />
* [[Topway LCD]] - supplier from Shenzhen, Mainland China<br />
<br />
== Photo Diode ==<br />
A diode with its junction exposed to light will generate a little bit of voltage and current ( if the circuit resistance is not infinite ). Diodes that are meant to exploit this are photo diodes, regular diodes often, but not always, are enclosed to keep out the light. The signal is not strong and lots of amplification can be useful.<br />
<br />
== Photo Transistor ==<br />
If a photo diode makes up one junction of a transistor the photo diode has a built in amplifier. This is the photo transistor. An advantage is that the signal is larger.<br />
<br />
== Photo Multiplier ==<br />
This is a somewhat unusual ( for most experimenters ) device. It is a vacume tube with a series of electrodes at high voltage from each other. When a photon knocks an electron out of the first electrode it then knocks out more on the second electrode and so on. They can be very sensitive, I think down to single electrons.<br />
<br />
== Solid State Laser ==<br />
== Optical Isolator ==<br />
== Photo Resistor ==<br />
== Photovoltaic Cell ==<br />
# [http://en.wikipedia.org/wiki/Photovoltaics Photovoltaics - Wikipedia, the free encyclopedia]<br />
<br />
== VFD ==<br />
*life time - around 10000 to 30000hrs when dim down to 50% brightness<br />
*make sure no any dead pt<br />
*update rate - around 10mSec for each new update data<br />
*command for dim down<br />
*no electrostatic effect due to glass material</div>Yanhttp://www.opencircuits.com/index.php?title=Modulation_Plugin&diff=16854Modulation Plugin2008-11-25T03:27:14Z<p>Yan: /* Hardware Solution */ adding a svn server</p>
<hr />
<div>==ToDos==<br />
*make sure each components freq. response, to make sure the highest freq. <br />
*place DAC into this module board together, then only 4 wires(Vcc, I2C clk, Gnd & I2C data) from host. <br />
*understand all components<br />
*call sample<br />
*draw circuit and PCB and grounding problem<br />
*test by real circuit and firmware<br />
<br />
<br />
==Objectives==<br />
*The modulation module is used to deliver a digital output signal with the following characteristics:<br />
**Square wave<br />
**Variable frequency (>1kHz)<br />
**Variable amplitude (0V - 2.5V)<br />
*interface to MCU which do the control<br />
<br />
<br />
*Q: Is square wave where the "Lo" time is always at "GND" OK?<br />
*Q: If not, is a switch between "Lo is GND" vs. "Lo is negative Hi" OK? Or does "Lo" need to be independently controlled with another ADC?<br />
*Q: Will people be connecting a speaker directly to the output, requiring a relatively high-power output [[op amp]] such as the LM386N-3 ?<br />
<br />
<br />
==Software Solution==<br />
*Timer Interrupt controlling I2C 10-bit DAC can only achieve frequency response of about 1kHz<br />
**5byte/cmd<br />
**8bit/byte<br />
**baudrate = 400kHz<br />
**This yields 10kHz (0.1ms)<br />
**As OS context switch is 10ms, set timer to 1ms (1kHz), so that 0.9ms can be used to process other tasks<br />
*Due to higher freq. response requirement, so using hardware to implement the clock<br />
<br />
<br />
==Hardware Solution==<br />
<br />
===Overall Performance===<br />
*I2C Baudrate:<br />
*Output Voltage Range:<br />
*Output Frequency Range:<br />
*Number of channels:<br />
<br />
<br />
===Selected Chips===<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ <br />
! Part No. !! Description !! Order Chip || Call Sample<br />
|-valign="top"<br />
| [http://focus.ti.com/lit/ds/symlink/dac6574.pdf DAC6574IDGS] || Quad-channel 10-bit I2C DAC || Digikey || No need<br />
|-valign="top"<br />
| [http://download.cypress.com.edgesuite.net/design_resources/datasheets/contents/cy2545_8.pdf CY2545???] || Quad PLL I2C Programmable Clock Generator || HQEW || Try Contact Cypress<br />
|-valign="top"<br />
| [http://www.maxim-ic.com/quick_view2.cfm/qv_pk/4474 DS1089L] || 3.3V Center Spread-Spectrum EconOscillator || Digikey || Maxim<br />
|-valign="top"<br />
| [http://www.onsemi.com/pub/Collateral/MC74VHC4051-D.PDF MC74VHC4053DT] || Analog Multiplexers || || Try Contact ON Semiconductor<br />
|}<br />
CY2545 is out of stock in digikey, so there is no more information about it.<br />
<br />
<br />
===Circuit===<br />
<br />
+-----+ +--------+ +--------+<br />
I2C Bus | | | Analog | | Op-Amp |<br />
------------+-----| DAC |------------| Switch |---------| |---------Output<br />
| | | +--------+ +--------+<br />
| +-----+ |<br />
| |<br />
| +--------------+ |<br />
| | Programmable | |<br />
+-----| Clock |-------+<br />
+--------------+<br />
<br />
<br />
This architecture allows the square wave to run at a very high frequency, even with a slow I2C and a slow DAC.<br />
<br />
<br />
===Circuit Simulation by [http://www.falstad.com/circuit/ Paul Falstad's Web]===<br />
*Import the following<br />
<pre><nowiki><br />
$ 1 5.0E-6 16.817414165184545 64 5.0 50<br />
w 128 256 144 256 0<br />
w 16 256 64 256 0<br />
g 16 352 16 368 0<br />
v 64 64 112 64 0 0 40.0 2.5 0.0 0.0 0.5<br />
w 112 128 144 128 0<br />
w 64 128 16 128 0<br />
w 16 128 16 256 0<br />
v 64 256 128 256 0 2 1000.0 1.65 1.65 0.0 0.5<br />
a 336 144 464 144 1 3.3 0.0<br />
w 336 160 336 192 0<br />
w 464 192 464 144 0<br />
w 464 144 512 144 0<br />
r 592 144 592 256 0 1000.0<br />
g 592 352 592 368 0<br />
w 512 144 592 144 0<br />
w 336 192 352 192 0<br />
w 432 192 464 192 0<br />
v 64 128 112 128 0 1 1.0 1.25 1.25 0.0 0.5<br />
w 16 256 16 288 0<br />
w 16 288 16 352 0<br />
w 592 256 592 352 0<br />
g 272 352 272 368 0<br />
w 272 128 336 128 0<br />
w 176 256 176 144 0<br />
r 272 224 272 288 0 1000.0<br />
w 272 128 272 224 0<br />
w 272 288 272 352 0<br />
159 144 128 208 128 0<br />
r 208 128 256 128 0 1000.0<br />
w 256 128 272 128 0<br />
w 144 256 176 256 0<br />
r 336 224 336 288 0 1000.0<br />
g 336 352 336 368 0<br />
w 336 288 336 352 0<br />
w 336 192 336 224 0<br />
r 352 192 432 192 0 1000.0<br />
o 4 64 0 34 2.5 7.8125E-4 0 -1<br />
o 0 64 0 35 5.0 9.765625E-5 1 -1<br />
o 11 64 0 34 2.5 0.0015625 2 -1<br />
</nowiki></pre><br />
<br />
===[http://chungyan5.no-ip.org/vc/?root=modulation_plugin SVN SERVER]===<br />
<br />
==Components Inside Circuit==<br />
<br />
===DAC chip===<br />
*Part No: DAC6574IDGS<br />
*[http://focus.ti.com/lit/ds/symlink/dac6574.pdf datasheet]<br />
*Resolution: 10-bit<br />
*I2C clock Frequency: upto 3.4Mbps<br />
*No of channels: 4<br />
*Operating Voltage: 2.7 - 5.5V<br />
*Temperature range: -40 - 105<sup>o</sup>C<br />
<br />
<br />
===Clock Generator chip===<br />
*CY2545???<br />
*[http://download.cypress.com.edgesuite.net/design_resources/datasheets/contents/cy2545_8.pdf datasheet] <br />
*buy at [http://new.hqew.com/Web/Public/Buyer/ICStockSearch.aspx?keyword=cy2545 here]<br />
*I2C clock Frequency: upto 400kbps<br />
*No of channels: 4<br />
*Operating Voltage: 2.5V, 3.0V, 3.3V<br />
*Temperature range: -40 - 85<sup>o</sup>C<br />
<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Comparison between Different Clock Generator Chips<br />
! Part No. !! Opertating Volt !! Operating Freq !! Min Volt !! Max Volt !! output freq !! Min Temp !! Max Temp !! Pin<br />
|-valign="top"<br />
| CY2545 || 2.5V, 3.0V, 3.3V || 400KHz || -0.5V || 4.5V || 3- 166 MHz <br />
| -40<sup>o</sup>C || 85<sup>o</sup>C || 24-pin <br />
|-<br />
| DS1089L || 3.3V || 400KHz || 2.7V || 3.6V || 130kHz - 66.6MHz <br />
| -40<sup>o</sup>C || 85<sup>o</sup>C || 8-pin <br />
|}<br />
CLK 1-8 : frequency output<br />
CLK 3 : frequency selection (FS)<br />
(Function 2) cy2545 has 4 PLLs, each PLLs can be set 2 frequency, CLK 3 use to select the frequency<br />
CLK 6 : spread spectrum ON/OFF control input<br />
(Function 2) for synthesizing and modulating the frequency<br />
Vdd_CLK_BX (X=1,2,3) control the output frquency of Blanck X (X=1,2,3) <br />
<br />
+------------------+ <br />
| | |------CLK 1<br />
| | Bank 1 |<br />
| | |------CLK 2<br />
|------------------| <br />
| | |------CLK 3<br />
| | Bank 2 |------CLK 4<br />
| | |------CLK 5<br />
|------------------|<br />
| | |------CLK 6<br />
| | Bank 3 |------CLK 7<br />
| | |------CLK 8<br />
+------------------+<br />
CLKIN/RST ---1. 2.5V/3.0V/3.3V external reference clock frequency<br />
2. Reset function POR :back to default condition / <br />
Clean Start : keep the programmed value<br />
Xout Crystal frequency output<br />
Xin/EXCLKIN Crystal frequency input/ 1.8V external clock input<br />
<br />
*Coding<br />
[Start Bit]->[7-bits devices]-->[R/W bit]-->[ Slave ]-->[ 8-bits ]--> .. <br />
[ address ] [ address ] [ ] [ CLK ACK ] [memory address] <br />
<br />
..[ACK]-->[8-bits]-->[ 8-bits ]-->....[ 8-bits ]......until... [stop bit]<br />
[ ] [ data ] [data in MA+1] [data in MA+n] [ ]<br />
<br />
<br />
===Analog Switch===<br />
*Part No: MC74VHC4053<br />
*[http://www.onsemi.com/pub/Collateral/MC74VHC4051-D.PDF datasheet]<br />
*Switching Frequency: 120MHz<br />
*No of channels: 4<br />
*Operating Voltage: <br />
*Temperature range: -40 - 85<sup>o</sup>C<br />
<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Comparison between Different Analog Switches<br />
! Part No. !! Operating Volt(V) !! Freq Resp(Hz) at 3V !! On-state Resist(Ω) at 3V !! Min Volt(V) !! Max Volt(V) !! Min Temp !! Max Temp !! Indenpent Circuit !! Voltage Supply Source !! Pin<br />
|-valign="top"<br />
| [http://focus.ti.com/lit/ds/symlink/sn74ahc4066.pdf SN74AHC4066] || Vcc : 2V~5.5V || 35MHz || 29Ω || Vcc : -0.5V || Vcc : 7V||-40<sup>o</sup>C || 85<sup>o</sup>C || 4 || single || 14<br />
|-<br />
| [http://www.nxp.com/acrobat_download/datasheets/74HC_HCT4051_3.pdf 74HC4051D] || Vcc : 2V~10V Vee : -10V~2V || Nil || 80Ω || Vcc :-0.5V Vee : -11V || Vcc : 11V Vee : 2V ||-40<sup>o</sup>C || 85<sup>o</sup>C || 4 || Dual || 16<br />
|-<br />
| [http://www.onsemi.com/pub/Collateral/MC74VHC4051-D.PDF MC74VHC''4051''] || Vcc : 2V~6V Vee : -6V~0V || 80MHz || 80Ω || Vcc :-0.5V Vee :-7V || Vcc : 7V Vee : 5V ||-40<sup>o</sup>C || 85<sup>o</sup>C || 4 || Dual || 16<br />
|-<br />
| [http://www.onsemi.com/pub/Collateral/MC74VHC4051-D.PDF MC74VHC''4052''] || Vcc : 2V~6V Vee : -6V~0V || 90MHz || 90Ω || Vcc :-0.5V Vee :-7V || Vcc : 7V Vee : 5V ||-40<sup>o</sup>C || 85<sup>o</sup>C || 4 || Dual || 16<br />
|-<br />
| [http://www.onsemi.com/pub/Collateral/MC74VHC4051-D.PDF MC74VHC''4053''] || Vcc : 2V~6V Vee : -6V~0V || 120MHz || 90Ω || Vcc :-0.5V Vee :-7V || Vcc : 7V Vee : 5V ||-40<sup>o</sup>C || 85<sup>o</sup>C || 4 || Dual || 16<br />
|-<br />
|}<br />
<br />
*more information about the series 7400 in wiki: http://en.wikipedia.org/wiki/7400_series<br />
*there is model G which is super high speeds at more than 1 GHz in 7400 family, however this model is very expensive.<br />
<br />
<br />
===op-amp buffer===<br />
*OPA340<br />
<br />
<br />
==Possibly Useful References ==<br />
<br />
[http://www.ladyada.net/wiki/openbench/fgen An open source waveform generator]</div>Yanhttp://www.opencircuits.com/index.php?title=RS232_RS485_USB_Converter_Board&diff=16853RS232 RS485 USB Converter Board2008-11-25T03:11:29Z<p>Yan: /* Circuit and PCB */ update the viewvc path</p>
<hr />
<div>==Features==<br />
<!--<graphviz><br />
digraph blks_conn {<br />
mcu [shape=box, label="mcu"];<br />
RS232 [shape=box, label="rs232"];<br />
rs485_422 [shape=box, label="rs485/422"];<br />
usb [shape=box, label="slave usb"];<br />
comm [shape=box, label="common wires"];<br />
mcu -> comm [dir = both];<br />
comm -> RS232 [dir = both];<br />
comm -> rs485_422 [dir = both];<br />
comm -> usb [dir = both];<br />
}<br />
</graphviz>--><br />
*for low traffic and low speed application<br />
*mcu, RS232, RS485/RS422, slave usb all can be interchangeable.<br />
*usb side<br />
**support platform in linux with usb driver<br />
**simulated uart programming in application level<br />
*rs232 to rs485 side<br />
**Tested max. baudrate is 115200(i assume more high baudrate can be accepted, but i have not tested)<br />
<br />
<br />
==Technical==<br />
<br />
<br />
===RS232===<br />
*[http://www.realhamradio.com/tac32-interface.htm RS232 Circuit examples]<br />
<br />
===USB===<br />
*Host Computer Setting for usb connection<br />
**[http://www.ftdichip.com/ Using Solution from FTDI Chips]<br />
**[http://www.ftdichip.com/Drivers/FT2232CDrivers.htm#VCP Linux USB Driver and its usb api, a simulate uart api match to usb api FOR ftdichip]<br />
**References<br />
***[http://www.beyondlogic.org/usb/ftdi.htm beyondlogic for ftdi]<br />
***[http://ftdi-usb-sio.sourceforge.net/ sourceforge usb driver for ftdi]<br />
*chips<br />
**[http://chungyan5.no-ip.org/WebServerDocs/open_data/KnowledgeDb/ComputerSysDevelopment/apps/comm/converter/ds2232c_15.pdf ds2232c]<br />
<br />
<br />
===RS485===<br />
*chips<br />
**Linear Technology Corp., LTC2859 and LTC2861<br />
**[http://chungyan5.no-ip.org/WebServerDocs/open_data/KnowledgeDb/ComputerSysDevelopment/apps/comm/converter/DS3695.pdf DS3695]<br />
<br />
<br />
===Circuit and PCB===<br />
*[http://chungyan5.no-ip.org/vc/?root=converter gEDA Project Files]<br />
:OR [[Media:Converter.zip|Download here, not always updated]]<br />
:gEDA libraries can be download [http://www.opencircuits.com/PCB_Footprints here] or [http://chungyan5.no-ip.org/open_data/electronic_computer/eda/geda/libs more updated], then modify the gafrc inside converter/<br />
*We have components and PCB, Or some have already soldered, if needed email to us: [mailto:yan@amonics.com yan]<br />
<br />
==ToDo==<br />
*get a usb chips to uart, which with linux driver<br />
**MCT P87C52UBAA(http://pfranc.com/usb/usb.mhtml)<br />
**cypress, PSoC with USB<br />
*linux driver<br />
**driver in linux : http://ftdi-usb-sio.sourceforge.net/<br />
**usb in linux guide : http://www.linux-usb.org/USB-guide/book1.html<br />
*get a usb to rs232/485 converter driver<br />
**driver in windows : http://www.hexin-tech.com.cn/<br />
*re-design all PCB boards dimension following a mechanical box<br />
*merge RS232 board and RS232_dspic_prog board together<br />
**using 5 pins as TTL level connection, adding one more for RS485 ctrl, and pin layouts as "signal power signal power ..."<br />
*In the market, it has so many these kind of converter and very cheap price(<HK100) and they are including a small mechanical box(electronic does not complex, but mechanial box is complex), which is better than what we do by ourself.<br />
[[Category:Projects]]</div>Yanhttp://www.opencircuits.com/index.php?title=RS232_RS485_USB_Converter_Board&diff=16852RS232 RS485 USB Converter Board2008-11-25T03:09:26Z<p>Yan: /* ToDo */</p>
<hr />
<div>==Features==<br />
<!--<graphviz><br />
digraph blks_conn {<br />
mcu [shape=box, label="mcu"];<br />
RS232 [shape=box, label="rs232"];<br />
rs485_422 [shape=box, label="rs485/422"];<br />
usb [shape=box, label="slave usb"];<br />
comm [shape=box, label="common wires"];<br />
mcu -> comm [dir = both];<br />
comm -> RS232 [dir = both];<br />
comm -> rs485_422 [dir = both];<br />
comm -> usb [dir = both];<br />
}<br />
</graphviz>--><br />
*for low traffic and low speed application<br />
*mcu, RS232, RS485/RS422, slave usb all can be interchangeable.<br />
*usb side<br />
**support platform in linux with usb driver<br />
**simulated uart programming in application level<br />
*rs232 to rs485 side<br />
**Tested max. baudrate is 115200(i assume more high baudrate can be accepted, but i have not tested)<br />
<br />
<br />
==Technical==<br />
<br />
<br />
===RS232===<br />
*[http://www.realhamradio.com/tac32-interface.htm RS232 Circuit examples]<br />
<br />
===USB===<br />
*Host Computer Setting for usb connection<br />
**[http://www.ftdichip.com/ Using Solution from FTDI Chips]<br />
**[http://www.ftdichip.com/Drivers/FT2232CDrivers.htm#VCP Linux USB Driver and its usb api, a simulate uart api match to usb api FOR ftdichip]<br />
**References<br />
***[http://www.beyondlogic.org/usb/ftdi.htm beyondlogic for ftdi]<br />
***[http://ftdi-usb-sio.sourceforge.net/ sourceforge usb driver for ftdi]<br />
*chips<br />
**[http://chungyan5.no-ip.org/WebServerDocs/open_data/KnowledgeDb/ComputerSysDevelopment/apps/comm/converter/ds2232c_15.pdf ds2232c]<br />
<br />
<br />
===RS485===<br />
*chips<br />
**Linear Technology Corp., LTC2859 and LTC2861<br />
**[http://chungyan5.no-ip.org/WebServerDocs/open_data/KnowledgeDb/ComputerSysDevelopment/apps/comm/converter/DS3695.pdf DS3695]<br />
<br />
<br />
===Circuit and PCB===<br />
*[http://chungyan5.no-ip.org/vc/converter/ gEDA Project Files]<br />
:OR [[Media:Converter.zip|Download here, not always updated]]<br />
:gEDA libraries can be download [http://www.opencircuits.com/PCB_Footprints here] or [http://chungyan5.no-ip.org/open_data/electronic_computer/eda/geda/libs more updated], then modify the gafrc inside converter/<br />
*We have components and PCB, Or some have already soldered, if needed email to us: [mailto:yan@amonics.com yan]<br />
<br />
==ToDo==<br />
*get a usb chips to uart, which with linux driver<br />
**MCT P87C52UBAA(http://pfranc.com/usb/usb.mhtml)<br />
**cypress, PSoC with USB<br />
*linux driver<br />
**driver in linux : http://ftdi-usb-sio.sourceforge.net/<br />
**usb in linux guide : http://www.linux-usb.org/USB-guide/book1.html<br />
*get a usb to rs232/485 converter driver<br />
**driver in windows : http://www.hexin-tech.com.cn/<br />
*re-design all PCB boards dimension following a mechanical box<br />
*merge RS232 board and RS232_dspic_prog board together<br />
**using 5 pins as TTL level connection, adding one more for RS485 ctrl, and pin layouts as "signal power signal power ..."<br />
*In the market, it has so many these kind of converter and very cheap price(<HK100) and they are including a small mechanical box(electronic does not complex, but mechanial box is complex), which is better than what we do by ourself.<br />
[[Category:Projects]]</div>Yanhttp://www.opencircuits.com/index.php?title=RS232_RS485_USB_Converter_Board&diff=16851RS232 RS485 USB Converter Board2008-11-25T03:07:18Z<p>Yan: /* ToDo */</p>
<hr />
<div>==Features==<br />
<!--<graphviz><br />
digraph blks_conn {<br />
mcu [shape=box, label="mcu"];<br />
RS232 [shape=box, label="rs232"];<br />
rs485_422 [shape=box, label="rs485/422"];<br />
usb [shape=box, label="slave usb"];<br />
comm [shape=box, label="common wires"];<br />
mcu -> comm [dir = both];<br />
comm -> RS232 [dir = both];<br />
comm -> rs485_422 [dir = both];<br />
comm -> usb [dir = both];<br />
}<br />
</graphviz>--><br />
*for low traffic and low speed application<br />
*mcu, RS232, RS485/RS422, slave usb all can be interchangeable.<br />
*usb side<br />
**support platform in linux with usb driver<br />
**simulated uart programming in application level<br />
*rs232 to rs485 side<br />
**Tested max. baudrate is 115200(i assume more high baudrate can be accepted, but i have not tested)<br />
<br />
<br />
==Technical==<br />
<br />
<br />
===RS232===<br />
*[http://www.realhamradio.com/tac32-interface.htm RS232 Circuit examples]<br />
<br />
===USB===<br />
*Host Computer Setting for usb connection<br />
**[http://www.ftdichip.com/ Using Solution from FTDI Chips]<br />
**[http://www.ftdichip.com/Drivers/FT2232CDrivers.htm#VCP Linux USB Driver and its usb api, a simulate uart api match to usb api FOR ftdichip]<br />
**References<br />
***[http://www.beyondlogic.org/usb/ftdi.htm beyondlogic for ftdi]<br />
***[http://ftdi-usb-sio.sourceforge.net/ sourceforge usb driver for ftdi]<br />
*chips<br />
**[http://chungyan5.no-ip.org/WebServerDocs/open_data/KnowledgeDb/ComputerSysDevelopment/apps/comm/converter/ds2232c_15.pdf ds2232c]<br />
<br />
<br />
===RS485===<br />
*chips<br />
**Linear Technology Corp., LTC2859 and LTC2861<br />
**[http://chungyan5.no-ip.org/WebServerDocs/open_data/KnowledgeDb/ComputerSysDevelopment/apps/comm/converter/DS3695.pdf DS3695]<br />
<br />
<br />
===Circuit and PCB===<br />
*[http://chungyan5.no-ip.org/vc/converter/ gEDA Project Files]<br />
:OR [[Media:Converter.zip|Download here, not always updated]]<br />
:gEDA libraries can be download [http://www.opencircuits.com/PCB_Footprints here] or [http://chungyan5.no-ip.org/open_data/electronic_computer/eda/geda/libs more updated], then modify the gafrc inside converter/<br />
*We have components and PCB, Or some have already soldered, if needed email to us: [mailto:yan@amonics.com yan]<br />
<br />
==ToDo==<br />
*get a usb chips to uart, which with linux driver<br />
**MCT P87C52UBAA(http://pfranc.com/usb/usb.mhtml)<br />
**cypress, PSoC with USB<br />
*linux driver<br />
**driver in linux : http://ftdi-usb-sio.sourceforge.net/<br />
**usb in linux guide : http://www.linux-usb.org/USB-guide/book1.html<br />
*get a usb to rs232/485 converter driver<br />
**driver in windows : http://www.hexin-tech.com.cn/<br />
*re-design all PCB boards dimension<br />
*merge RS232 board and RS232_dspic_prog board together<br />
*In the market, it has so many these kind of converter and very cheap price(<HK100) and they are including a small mechanical box(electronic does not complex, but mechanial box is complex), which is better than what we do by ourself.<br />
[[Category:Projects]]</div>Yanhttp://www.opencircuits.com/index.php?title=Optoelectronics&diff=16765Optoelectronics2008-11-13T12:41:25Z<p>Yan: /* Photovoltaic Cell */ VFD</p>
<hr />
<div>Optoelectronics are devices that are some combination of electrical and optical. Perhaps the simplest is the Light Emitting Diode or LED which converts electrical energy into light. A listing of some optoelectronic devices follows.<br />
<br />
<br />
== LEDs ==<br />
LEDs are diodes designed to produce visible light.<br />
<br />
Commonly a small low power device that makes a not too bright light. High power, high brightness versions are now becoming widely available. The low power ones typically run on a volt or so, at about 10 ma. Typically they are run on higher voltages with a current limiting resistor that sets the current. Current control is almost always required ( often with a resistor ) as LED are very sensitive to small voltage changes. Like other diodes they conduct only in one direction.<br />
<br />
When using a LED in a cicuit it's important to use a current limiter such as a resistor. When using resistors measure the foreward voltage drop of the LED with a multimeter, subtract this from the supply voltage, then plug the difference into ohms law to calculate the required resistor value. Different color LEDs all have different voltage drops.<br />
<br />
Uses<br />
*Indicator<br />
*Part of 7 segment display<br />
*Light source<br />
<br />
External Links<br />
<br />
# [http://en.wikipedia.org/wiki/Light_Emitting_Diode Light-emitting diode From Wikipedia, the free encyclopedia]<br />
# [http://www.iguanalabs.com/1stled.htm Learning About Transistors and LEDs]<br />
# [http://www.piclist.com/techref/io/led/pulse.htm?key=base+resistor&from= Brighter Appearance through pulsing]<br />
# [http://www.uchobby.com/index.php/2008/02/25/improving-the-ping-pong-ball-led-diffuser/ Improving the Ping Pong Ball LED Diffuser ]<br />
# [[Basic_Circuits_and_Circuit_Building_Blocks#Light_Emitting_Diode_.28_with_current_limiting_resistor_.29 ]]<br />
<br />
== LCDs ==<br />
<br />
Liquid Crystal Displays<br />
* Serial - These displays have a microcontroller on the display with a serial or I2C connection. Several builtin fonts are typically included. These displays are very easy to use, but the update rate for a display is very slow. Fullblown bitmap support is usually not available. Typical price for these displays is $50+.<br />
<br />
* Parallel - Parallel displays connect to a microcontroller via a parallel interface( the bitwidth varies from 8bits to 32bits ). Displays can have a much faster update rate then serial since they allow arbitrary graphs to be display. The displays are typically much cheaper then serial display starting as low as $20.<br />
<br />
Finding LCD displays is not easy since huge distributors such as Digikey have a limited selection. <br />
<br />
Some places that do have LCDs for hobby use:<br />
<br />
* [http://www.sparkfun.com Sparkfun] - Has a good selection of both parallel and serial displays. <br />
* [http://www.matrixorbital.com MatrixOrbital] - Specializes in serial display especially the type for direct connection to a PC.<br />
* [http://www.jameco.com Jameco] - A small selection. Mostly serial.<br />
* [http://www.seeedstudio.com/depot Seeedstudio] - Free sourcing services with some stock of basic LCD.<br />
<br />
== Photo Diode ==<br />
A diode with its junction exposed to light will generate a little bit of voltage and current ( if the circuit resistance is not infinite ). Diodes that are meant to exploit this are photo diodes, regular diodes often, but not always, are enclosed to keep out the light. The signal is not strong and lots of amplification can be useful.<br />
<br />
== Photo Transistor ==<br />
If a photo diode makes up one junction of a transistor the photo diode has a built in amplifier. This is the photo transistor. An advantage is that the signal is larger.<br />
<br />
== Photo Multiplier ==<br />
This is a somewhat unusual ( for most experimenters ) device. It is a vacume tube with a series of electrodes at high voltage from each other. When a photon knocks an electron out of the first electrode it then knocks out more on the second electrode and so on. They can be very sensitive, I think down to single electrons.<br />
<br />
== Solid State Laser ==<br />
== Optical Isolator ==<br />
== Photo Resistor ==<br />
== Photovoltaic Cell ==<br />
# [http://en.wikipedia.org/wiki/Photovoltaics Photovoltaics - Wikipedia, the free encyclopedia]<br />
<br />
== VFD ==<br />
*life time - around 10000 to 30000hrs when dim down to 50% brightness<br />
*make sure no any dead pt<br />
*update rate - around 10mSec for each new update data<br />
*command for dim down<br />
*no electrostatic effect due to glass material</div>Yanhttp://www.opencircuits.com/index.php?title=Programming_the_Device&diff=16715Programming the Device2008-11-03T07:56:54Z<p>Yan: /* Loading Firmware */</p>
<hr />
<div>==Requirements==<br />
<br />
===Hardware===<br />
#PC with COM port (Windows XP Installed for MPLAB)<br />
#ICD2 Programmer<br />
#Target Board<br />
#5V Power Supply<br />
<br />
===Software===<br />
#[http://ww1.microchip.com/downloads/en/DeviceDoc/MP750.zip MPLAB IDE v7.50]: v7.60 is not compatible with our current [http://www.sure-electronics.com/ ICD2 Programmers]. There are consistent "Devices cannot be founded" warnings.<br />
#[http://chungyan5.no-ip.org/websvn/listing.php dsPicProgrammer] ('''dsPicProgrammer.jar''')<br />
<br />
===Files===<br />
#[http://chungyan5.no-ip.org/websvn/listing.php dsPicBootloader] ('''bl_5011.hex'''). Original assembly code by ingenia can be downloaded from [http://www.ingenia-cat.com/download/iBL.s here].<br />
#Application hex file (e.g. '''app.hex''')<br />
<br />
<br />
==Loading Bootloader (Once only)==<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Loading Bootloader<br />
! Step !! Remarks <br />
|-valign="top"<br />
| Install [http://ww1.microchip.com/downloads/en/DeviceDoc/MP750.zip MPLAB IDE] || <br />
*Do '''NOT''' connect ICD 2 (via USB) to PC<br />
*Execute '''MPLAB vX.XX Install.exe'''<br />
|-valign="top"<br />
| Install USB Driver ||<br />
*Follow the instruction in (C:\Program Files\Microchip\MPLAB IDE\ICD2\Drivers\Ddicd2.htm)<br />
|-valign="top"<br />
| Select Target Chip ||<br />
*Run MPLAB IDE on PC<br />
*Select: Configure>Select Devices...<br />
*Choose dsPIC30F5011<br />
|-valign="top"<br />
| Target <-> ICD 2 ||<br />
*Use six pin cable. Beware of the pin assignments. Only pin 1 - 5 should be used.<br />
*Place Jumper on target board (if any). The Jumper connects target V<sub>cc</sub> to ICD 2.<br />
*Do '''NOT''' power-up the target.<br />
|-valign="top"<br />
| ICD 2 <-> PC ||<br />
*Plug-in ICD 2 to PC via USB cable<br />
*Power-up the target.<br />
*Select: Programmer>Select Programmer>MPLAB ICD 2<br />
*If this is the first time the ICD 2 is connected to PC, MPLAB IDE will automatically download the required OS to ICD 2, wait until it has finished<br />
*If you have not connected and powered up the target, you might see Warnings on invalid device IDs, and/or running self tests.<br />
*See results of self test if necessary: Programmer>Settings, Status Tab. Refer to [http://ww1.microchip.com/downloads/en/DeviceDoc/51331B.pdf ICD2 User's Guide] Chapter 7.<br />
|-valign="top"<br />
| Load Bootloader ||<br />
*Select: File>Import...<br />
*Select '''bl_5011.hex'''<br />
|-valign="top"<br />
| Start Programming ||<br />
*Select: Programmer>Program<br />
|-valign="top"<br />
| Finishing ||<br />
*Power-down the Taget<br />
*Select: Programmer>Select Programmer>None<br />
*Unplug USB cable<br />
|-<br />
|}<br />
<br />
<br />
==Loading Firmware==<br />
*Download [http://chungyan5.no-ip.org/open_data/electronic_computer/platforms/dspic/dsPicProgrammer/dsPicProgrammer1.5.5.zip dsPic_Programmer.zip] or [http://chungyan5.no-ip.org/open_data/electronic_computer/platforms/dspic/dsPicProgrammer/ws/ updated directory]<br />
*Save to a directory.<br />
::e.g. desktop<br />
*Unzip the dsPic_Programmer.zip, then you have an unziped file.<br />
[[Image:prog_guid_dl.JPG]]<br />
<br />
----<br />
<br />
*Drag the unzip file to a director.<br />
::eg. USB memory devics<br />
[[Image:prog_guid_drag.JPG]]<br />
<br />
----<br />
<br />
*Save your .hex file(foo.hex) to your directory location <br />
::e.g. X:\dsPic_Programmer\ ---> X:\ is the driver where the dsPic_Programmer located<br />
[[Image:prog_guid_hex.JPG]]<br />
===Download Firmware===<br />
*Start a Command Prompt<br />
**Start -> Run<br>[[Image:2 1 run.JPG]]<br><br />
**Enter cmd<br>[[Image:2 2 cmd.JPG]]<br><br />
*Run dsPicProgrammer<br />
**Make sure your device is connected through a "Direct RS232 Cable" to PC Serial Port. <br />
**Change to the directory where dsPicProgrammer.jar is located and run the command:<br />
***for example, jre\bin\java -Djava.library.path=.\rxtx\bin -jar dspicProgrammer.jar COM1 115200 foo.hex<br />
***Or directly using dsPicProgrammer.bat COM1 115200 foo.hex(Windows)<br />
***java -jar dsPicProgrammer.jar /dev/ttyS0 115200 foo.hex (Linux)<br />
:::where COM1 is your COM Port ID<br />
:::115200 is communication speed [in bps]<br />
:::foo.hex is your firmware new file<br />
::[[Image:2 3 command.JPG]]<br />
:*When the program prompt you for an input, press y:<br>[[Image:2 4 prompt.JPG]]<br><br />
:*If communication can be established, you should see something like this:<br>[[Image:2 5 progress.JPG]]<br><br />
:*Wait until programming is completed.<br>[[Image:2 6 complete.JPG]]<br><br />
:*after all completed, power OFF your device, then power ON again, enjoy your new updated.<br />
<br />
==Troubleshooting==<br />
===Invalid COM Port===<br />
*In case of selecting an invalid COM port, you should see the error message:<br>gnu.io.NoSuchPortException: Choosing COM Port Error<br>[[Image:3 1 com err.JPG]]<br><br><br />
===Missing firmware file===<br />
*In case of selecting a firmware file that does not exist, you should see the error message:<br>java.io.FileNotFoundException: foo1.hex <The system cannot find the file specified><br>[[Image:3 2 file err.JPG]]<br><br><br />
===Missing RXTX driver===<br />
*In case of missing the RXTX driver, you should see the error message:<br>Exception in thread “main” java.lang.NoClassDefFoundError: gnu/io/UnsupportedCommOperationException<br>[[Image:3 3 rxtx err.JPG]]<br><br></div>Yanhttp://www.opencircuits.com/index.php?title=Programming_the_Device&diff=16714Programming the Device2008-11-03T07:54:42Z<p>Yan: /* Loading Firmware */ update dspicprogrammer ws</p>
<hr />
<div>==Requirements==<br />
<br />
===Hardware===<br />
#PC with COM port (Windows XP Installed for MPLAB)<br />
#ICD2 Programmer<br />
#Target Board<br />
#5V Power Supply<br />
<br />
===Software===<br />
#[http://ww1.microchip.com/downloads/en/DeviceDoc/MP750.zip MPLAB IDE v7.50]: v7.60 is not compatible with our current [http://www.sure-electronics.com/ ICD2 Programmers]. There are consistent "Devices cannot be founded" warnings.<br />
#[http://chungyan5.no-ip.org/websvn/listing.php dsPicProgrammer] ('''dsPicProgrammer.jar''')<br />
<br />
===Files===<br />
#[http://chungyan5.no-ip.org/websvn/listing.php dsPicBootloader] ('''bl_5011.hex'''). Original assembly code by ingenia can be downloaded from [http://www.ingenia-cat.com/download/iBL.s here].<br />
#Application hex file (e.g. '''app.hex''')<br />
<br />
<br />
==Loading Bootloader (Once only)==<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Loading Bootloader<br />
! Step !! Remarks <br />
|-valign="top"<br />
| Install [http://ww1.microchip.com/downloads/en/DeviceDoc/MP750.zip MPLAB IDE] || <br />
*Do '''NOT''' connect ICD 2 (via USB) to PC<br />
*Execute '''MPLAB vX.XX Install.exe'''<br />
|-valign="top"<br />
| Install USB Driver ||<br />
*Follow the instruction in (C:\Program Files\Microchip\MPLAB IDE\ICD2\Drivers\Ddicd2.htm)<br />
|-valign="top"<br />
| Select Target Chip ||<br />
*Run MPLAB IDE on PC<br />
*Select: Configure>Select Devices...<br />
*Choose dsPIC30F5011<br />
|-valign="top"<br />
| Target <-> ICD 2 ||<br />
*Use six pin cable. Beware of the pin assignments. Only pin 1 - 5 should be used.<br />
*Place Jumper on target board (if any). The Jumper connects target V<sub>cc</sub> to ICD 2.<br />
*Do '''NOT''' power-up the target.<br />
|-valign="top"<br />
| ICD 2 <-> PC ||<br />
*Plug-in ICD 2 to PC via USB cable<br />
*Power-up the target.<br />
*Select: Programmer>Select Programmer>MPLAB ICD 2<br />
*If this is the first time the ICD 2 is connected to PC, MPLAB IDE will automatically download the required OS to ICD 2, wait until it has finished<br />
*If you have not connected and powered up the target, you might see Warnings on invalid device IDs, and/or running self tests.<br />
*See results of self test if necessary: Programmer>Settings, Status Tab. Refer to [http://ww1.microchip.com/downloads/en/DeviceDoc/51331B.pdf ICD2 User's Guide] Chapter 7.<br />
|-valign="top"<br />
| Load Bootloader ||<br />
*Select: File>Import...<br />
*Select '''bl_5011.hex'''<br />
|-valign="top"<br />
| Start Programming ||<br />
*Select: Programmer>Program<br />
|-valign="top"<br />
| Finishing ||<br />
*Power-down the Taget<br />
*Select: Programmer>Select Programmer>None<br />
*Unplug USB cable<br />
|-<br />
|}<br />
<br />
<br />
==Loading Firmware==<br />
*Download [http://chungyan5.no-ip.org/open_data/electronic_computer/platforms/dspic/dsPicProgrammer/dsPicProgrammer1.5.5.zip dsPic_Programmer.zip] or [http://chungyan5.no-ip.org/open_data/electronic_computer/platforms/dspic/dsPicProgrammer/ws/ updated directory]<br />
http://chungyan5.no-ip.org/open_data/electronic_computer/platforms/dspic/dsPicProgrammer/ws/<br />
*Save to a directory.<br />
::e.g. desktop<br />
*Unzip the dsPic_Programmer.zip, then you have an unziped file.<br />
[[Image:prog_guid_dl.JPG]]<br />
<br />
----<br />
<br />
*Drag the unzip file to a director.<br />
::eg. USB memory devics<br />
[[Image:prog_guid_drag.JPG]]<br />
<br />
----<br />
<br />
*Save your .hex file(foo.hex) to your directory location <br />
::e.g. X:\dsPic_Programmer\ ---> X:\ is the driver where the dsPic_Programmer located<br />
[[Image:prog_guid_hex.JPG]]<br />
===Download Firmware===<br />
*Start a Command Prompt<br />
**Start -> Run<br>[[Image:2 1 run.JPG]]<br><br />
**Enter cmd<br>[[Image:2 2 cmd.JPG]]<br><br />
*Run dsPicProgrammer<br />
**Make sure your device is connected through a "Direct RS232 Cable" to PC Serial Port. <br />
**Change to the directory where dsPicProgrammer.jar is located and run the command:<br />
***for example, jre\bin\java -Djava.library.path=.\rxtx\bin -jar dspicProgrammer.jar COM1 115200 foo.hex<br />
***Or directly using dsPicProgrammer.bat COM1 115200 foo.hex(Windows)<br />
***java -jar dsPicProgrammer.jar /dev/ttyS0 115200 foo.hex (Linux)<br />
:::where COM1 is your COM Port ID<br />
:::115200 is communication speed [in bps]<br />
:::foo.hex is your firmware new file<br />
::[[Image:2 3 command.JPG]]<br />
:*When the program prompt you for an input, press y:<br>[[Image:2 4 prompt.JPG]]<br><br />
:*If communication can be established, you should see something like this:<br>[[Image:2 5 progress.JPG]]<br><br />
:*Wait until programming is completed.<br>[[Image:2 6 complete.JPG]]<br><br />
:*after all completed, power OFF your device, then power ON again, enjoy your new updated.<br />
<br />
==Troubleshooting==<br />
===Invalid COM Port===<br />
*In case of selecting an invalid COM port, you should see the error message:<br>gnu.io.NoSuchPortException: Choosing COM Port Error<br>[[Image:3 1 com err.JPG]]<br><br><br />
===Missing firmware file===<br />
*In case of selecting a firmware file that does not exist, you should see the error message:<br>java.io.FileNotFoundException: foo1.hex <The system cannot find the file specified><br>[[Image:3 2 file err.JPG]]<br><br><br />
===Missing RXTX driver===<br />
*In case of missing the RXTX driver, you should see the error message:<br>Exception in thread “main” java.lang.NoClassDefFoundError: gnu/io/UnsupportedCommOperationException<br>[[Image:3 3 rxtx err.JPG]]<br><br></div>Yanhttp://www.opencircuits.com/index.php?title=Techniques&diff=16688Techniques2008-10-30T09:04:49Z<p>Yan: /* Step by Step by using Software Design Tool */ fine tune the arrangement</p>
<hr />
<div>There are a wide variety of techniques used in electronics.<br />
<br />
<br />
== Printed circuit board design/fabrication ==<br />
=== Overview ===<br />
=== Software Design ===<br />
See [[#Software_design_tools|Software Design Tools]] below.<br />
<br />
==== Step by Step by using Software Design Tool ====<br />
*make sure the dimension and shape of PCB<br />
*make sure the size and location of Via for PCB stand<br />
*Make sure each components footprint.<br />
*each components are placed on suitable place by put on a hardcopy of simulation PCB<br />
*All components get enough clearance between them.<br />
*Silkscreen layout is confirmed.<br />
*PCB is drawn.<br />
*silkscreen adding the following:<br />
**version no.<br />
**organization name<br />
**board name<br />
*Netlist is ran and got a no error result.<br />
*DRC is ran and got a no error result.<br />
*Overall is checked.<br />
*generate Gerber and send to [[PCB Manufacturers]].<br />
<br />
=== Manual Design ===<br />
Somepeople do this with layout on clear film or by directly drawing on a circuit board, of even by scratching, grinding.... For now let them google this.<br />
<br />
=== Homebrew fabrication ===<br />
Before exploring these techniques, you should understand your options with regard to services such as ExpressPCB.com and PCB123.com. Being able to have several boards fabbed in 2 days for $59 (for example) makes it harder to justify the hassle of etching your own boards at home.<br />
* [http://www.electricstuff.co.uk/pcbs.html "How to make really really good homemade PCBs"] by Mike Harrison 2007<br />
* [[Toner Transfer]] -- This method involves laser printing your PCB design onto paper, then transferring toner onto copper-clad board.<br />
* [[Photoetching]] -- Exposure of PCB designs onto photosensitized copper-clad board.<br />
* [[Chemical Etchants]]<br />
* [http://groups.yahoo.com/group/pcb-gcode "Mechanically etching or milling PCBs. No chemicals!"] -- Use your CNC router/mill to make PC boards.<br />
<br />
=== Commercial PCB fabrication ===<br />
* [[Submitting PCB's for fabrication]] -- Common processes for submitting PCB's for fabrication.<br />
* [[PCB Manufacturers]]<br />
* [http://diydrones.com/profiles/blog/show?id=705844%3ABlogPost%3A30196 "PCB fabbing advice"] by Chris Anderson 2008<br />
<br />
== Circuit construction (Prototyping - Other than custom PCB) ==<br />
<br />
* [[Solderless protoboard]] ([http://en.wikipedia.org/wiki/Breadboard Wikipedia:Breadboard]) ([http://www.best-microcontroller-projects.com/prototyping.html a simple example with a small microcontroller])<br />
* [[Point-to-point]] ([http://en.wikipedia.org/wiki/Point-to-point_construction Wikipedia:Point-to-point construction])<br />
* [[Wirewrap]] ([http://en.wikipedia.org/wiki/Wire_wrap Wikipedia:Wire Wrap])<br />
* [[Dead bug style]] -- and a similar method, [http://ciphersbyritter.com/RADELECT/BREADBD/BREADBD.HTM "A Modern Breadboarding Technology: Insulating Pads Soldered to a Ground Plane"]<br />
* [[Manhattan style]]<br />
<br />
[[http://www.techlib.com/electronics/construction.html "Construction Ideas"]] has nice photographs of the above circuit construction techniques.<br />
<br />
* [[Stripboard]] (Veroboard): ([http://en.wikipedia.org/wiki/Stripboard Wikipedia:stripboard].)<br />
<br />
== Soldering techniques ==<br />
<br />
* [[Basic soldering]] -- How to use a soldering iron.<br />
* Surface Mount<br />
** [[Skillet reflow]]<br />
** [[Toaster oven reflow]]<br />
** [[Hot air soldering]]<br />
** [http://en.wikipedia.org/wiki/User:WillWare/Homebrew_surface-mount_construction A few different SMT assembly methods] that you can do at home on a cheap budget<br />
* [[Rework]] -- Techniques for fixing mistakes, or for adding new features to a board that ''almost'' does what you want.<br />
** [http://workmanship.nasa.gov/lib/insp/2%20books/links/sections/302_jumper%20wires.html official NASA recommendations for adding discrete wiring ("jumper wires") to PCBs]<br />
<br />
(Have you seen this [http://www.hackaday.com/2007/06/04/cnc-solder-paste-pick-n-place/ CNC solder paste/pick n place] ?)<br />
<br />
== [[Hardware tool]]s ==<br />
A directory of [[hardware tool]]s that you may find useful.<br />
<br />
== Software design tools ==<br />
<br />
Some people still build circuits without ever using any software tools.<br />
For complicated circuits, software design tools can save a lot of time.<br />
<br />
Here we list "suites" that combine schematic capture, component editor for the components used in schematic capture, circuit simulation, PCB layout, autorouter, and footprint editor for the footprints used in PCB layout.<br />
(Is there another place for listing stand-alone tools such as a [[switching regulator|switching power supply]] "wizard" and a RF analysis tool?)<br />
<br />
Quite often people mix-and-match tools -- using a schematic capture from one suite to generate pretty schematics and a netlist, then importing the netlist a third party Specctra autorouter, then importing the result into a PCB layout program from another suite for the final manual clean-up and design rule checking.<br />
<br />
In no particular order:<br />
<!-- Please use a valid license ie, BSD, GPL, Crippleware, Nagware, Shareware, Payware etc.. And specify platform. There's usually a lot of free win32 crippleware without sources makeing you victim of the design file hostage scenario. Also some packages are sub-packages to others, thus maybe no needing an entry of their own. --><br />
{| class="wikitable"<br />
|- <br />
! Name !! Platform !! License !! AutoRouter !! Comments<br />
|-<br />
| [http://www.liquidpcb.org/ Liquid PCB] || Linux, Win32 || GPL || no || [http://liquidpcb.wiki.sourceforge.net/ Liquid PCB wiki at SourceForge] Liquid PCB is a computer aided design application for designing printed circuit boards. You are not restricted to straight tracks and 45º angles, you can draw tracks any way you like. The tracks will move and bend as required to maintain your design rules. It is open source, and still in the Alpha stage.<br />
|-<br />
|[http://geda.seul.org/ [[gEDA]]] || Linux, *BSD || Free, OSS || autorouter || [http://geda.seul.org/wiki/ gEDA wiki] includes schematic and [http://sourceforge.net/projects/pcb/ PCB] for makeing [[gerber|gerbers]] etc...<br />
|-<br />
|[http://mccad.com/ McCAD EDS Lite] || MacOSX, Win32 || Free demo max 200 pin || autorouter || Free demo version available for download, 200 pin limit<br />
|-<br />
|[http://applefritter.com/replica McCAD EDS SE] || MacOSX, Win32 || "free"? || autorouter || Free with book, "Apple I Replica Creation". Supports 750 pins, 11"x17" sheet size, 6-8 data layers. <tangent>(any useful tips in this book for those who want to build a CPU from scratch?) <reply>No, there are not. The book is more entry-level. - Tom Owad</reply></tangent> <br />
|-<br />
|[http://www.freepcb.com/ FreePCB] || Win32 || GPL || can use [http://www.freerouting.net/ FreeRoute] || PCB Design Software<br />
|-<br />
|[http://tinycad.sourceforge.net/ TinyCAD] || Win32 || LGPL || n/a || Schematic Drawing Software <br />
|-<br />
|[http://kicad.sourceforge.net/ KiCad] || BSD, Linux, MacOSX, Win32 || GPL || autorouter || http://www.lis.inpg.fr/realise_au_lis/kicad/ EDA suite ; [http://kicad.sourceforge.net/wiki/ KiCad wiki]<br />
|-<br />
|[http://expresspcb.com/ Express SCH/PCB] || Win32 || Free use crippleware || ? || ExpressPCB's propietatary free schematic capture & PCB layout designer locking you to use ExpressPCB for manufacture explicitly. Manufacture in 3 business days of two boards for ~100 USD.<br />
|-<br />
|[http://altium.com/ Protel DXP] || Win32 || || autorouter || [http://techref.massmind.org/techref/app/protel.htm independent Protel users FAQ] <br />
|-<br />
|[http://cadsoftusa.com/ Eagle] [[Eagle Links]] || Win32, Linux || Free use crippleware || || ( Russ Hensel says>> ) I have been kicking around as a hobbyist for a while and Eagle seems to be the main hobbyist circuit/pcb cad program. It supports schematics and board layout with an auto-router. The free version can easily support 2 dual op amps with wide traces and a one sided board. There is quite a lot of info on the Internet and many projects supply eagle files. There is also a $125 non profit version supporting larger boards. It then gets expensive. Eagle is not really easy to learn: cut for it would be copy in almost any other program. It probably deserves a page or more of its own. ( << end RH ) <br>http://cadsoft.de/ <br>[http://www.sparkfun.com/tutorial/PCB/eagle-output-tutorial.htm Eagle tutorial from Sparkfun] <br>[http://www.makezine.com/blog/archive/2006/03/how_to_make_a_custom_library_p.html Eagle tutorial (makezine)] <br />
|-<br />
|[http://diptrace.com/ DipTrace] || || Crippleware || || 250-pin Freeware or Purchase more advanced versions<br />
|-<br />
|[http://winqcad.com/ WinQcad] || || Crippleware || || Demo with max 499 pins available for download <br />
|-<br />
|[http://www.hutson.co.nz/ Rimu Schematic and Rimu PCB] || Win32 || Payware || || Schematic & PCB design for MS-Windows<br />
|-<br />
|[http://mentala.com/ SuperCAD and SuperPCB] || Win32 || || || Mental Automation schematic & PCB for MS-Windows<br />
|-<br />
|[http://www.autotraxeda.com/ autotraxeda.com] || || || || AUTOTraxEDA needs MS-NT, won't work on MS-W98/ME. User forums have shown a certain lack of satisfaction with the program.<br />
|-<br />
|[http://www.holophase.com/dleval.htm holophase.com/dleval] || Win32 || Crippleware || || Circad's DOS version is free for non-commercial use.<br />
|-<br />
|[http://www.geda.seul.org/ geda.seul.org] || BSD, Linux, MacOSX || GPL || autorouter || xNIX Electronic Design Automation project has Schematic capture with PCB CAD.<br />
|-<br />
|[http://www.vutrax.co.uk/pricing.htm vutrax.co.uk/pricing] || Win32 || || autorouter || Vutrax for MS-Windows. Free for under 256 component pins.<br />
|-<br />
|[http://www.interactiv.com interactiv.com] || || || || Electronic Workbench, 400 USD for 500 pins. Includes schematic capture and simulation, virtual instruments and PCB layout. Said to be stable.<br />
|-<br />
|[http://pcb.sourceforge.net Harry Eaton's PCB] || BSD?, Linux?, MacOSX?, Win32 || GPL || autorouter || PCB design program which can work under any POSIX compliant operating system like Linux (or BSD under API compability layer). Have Gerber and PostScript output options.<br />
|-<br />
|[http://www.labcenter.co.uk/ labcenter.co.uk] || || || || They have a lite version "PIC bundle" ~149 USD includes schematic + simulation + pcb layout. You can write pic code for your pic schematic design and simulate. Even multi-pic, keypad, lcd display. Right now it can only simulate PIC16x83, PIC16x84 (lite version limited to 1k program code). Working on more pic modules. Will not produce Gerber or Excellion drill files. Only dxf, bmp, hpgl, tiff output (not sufficient!).<br />
|-<br />
|[http://www.ivex.com/ ivex.com] || || Payware || || Winboard PCB Layout, now [http://www.calcentron.com/Pages/NTEHomePage/ivex_cad_software.htm calcentron.com].<br />
|-<br />
|[http://www.illuminated.com.au/ illuminated.com.au] || Linux, Win32, DOS<!-- Claimed --> || || || Draftcad, Schematic Capture and PCB Design<br />
|-<br />
|[http://www.winqcad.com/ winqcad.com] || Win32, Linux+Wine || || || MicroCad<br />
|-<br />
| [http://www.4pcb.com/index.php?load=content&page_id=46 "PCB ARTIST"] || Win32 || ? || || schematic + layout. Seems to lock you into using Advanced Circuits for manufacture (?).<br />
|-<br />
| [http://www.sunstone.com/PCB123.aspx PCB123] || Win32 || ? || || schematic + layout. Seems to lock you into using Sunstone for manufacture (?).<br />
|-<br />
| [http://www.best-microcontroller-projects.com/schematic-drawing-program.html ProSchematic] || Win32 || "free trial" || no || can make schematics that look almost like photographs of a solderless breadboard.<br />
<!--<br />
|-<br />
| name and link || platform(s) || License? || AutoRouter? || Comments<br />
--><br />
|}<br />
<br />
(Some of this information in this table came from the [http://techref.massmind.org/techref/pcbcads.htm list of software design tools at the Massmind]).<br />
<br />
A [http://sourceforge.net/search/?type_of_search=soft&words=schematic SourceForge search for "schematic"] lists dozens of tools.<br />
Other than the ones already listed above, what tools in that list are useful for open circuits?<br />
<br />
Is there any way to objectively compare these tools?<br />
How well did they do at the<br />
[http://www.pcbwest.com/topgun/ PCB Top Gun contest] ?<br />
<br />
Timing diagrams:<br />
* GTKWave Electronic Waveform Viewer http://intranet.cs.man.ac.uk/apt/projects/tools/gtkwave/<br />
* TimingTool http://www.timingtool.com/<br />
<br />
When you want to post a picture of a schematic or timing diagram on a web site, should you use JPEG or PNG?<br />
I hope these 2 pictures answer your question:<br />
<br />
* http://www.ninechime.com/gallery/sketch/StopJPEGing.jpg<br />
* http://www.ninechime.com/gallery/sketch/StopJPEGing.png<br />
<br />
== [[PC-Microcontroller Communications]] ==<br />
<br />
Discussion of the various methods to connect a microcontroller or embedded system to a PC...<br />
<br />
== Embedded System Programming and Testing ==<br />
To add to the confusion programming in embedded system can mean a person writing a program or a device called a programmer "burning" a program into a chip. This section is for the "burning" meaning of programming.<br />
<br />
* Many systems use [[JTAG]] for programming and testing. (Such as [http://en.wikibooks.org/wiki/Atmel_AVR Atmel AVR embedded systems]]).<br />
* Other systems use some other kind of in-circuit programming.<br />
* Some people use [http://en.wikibooks.org/wiki/Embedded_Systems/Bootloaders_and_Bootsectors bootloaders] to make re-programming a little quicker.<br />
<br />
-- not sure that this next one is not misplaced ? --<br />
''We're talking about "programming and testing" ? What else do you use to test op-amp circuits?''<br />
<br />
* Many people use an [[oscilloscope]] ([[o'scope]]). See [[oscilloscope]] for a list of Keith has made a list of low-cost o'scopesl [http://www.techtravels.org/amiga/amigablog/?p=167 "PC USB logic analyzers that cost under $1000."] for a list of low-cost logic analyzers.<br />
<br />
Humans writing a program almost always do it in a language. Here is a section that discusses some of these languages: [[Programming Languages]]<br />
<br />
== Enclosure ==<br />
<br />
* The Earth Signal should short to whole metal Case<br />
* Digital/Analog GND should separate to this Earth Signal, and should connect a Y-cap. to filter the noise between them.<br />
* Attention: do not place near between Earth Signal and Digital/Analog GND, otherwise some spark come out, and affect your whole system.<br />
<br />
== Further Reading ==<br />
<br />
* [http://airborn.com.au/method/ "Electronics Design" from Airborn] gives an overview of the complete process: specification, (schematic) circuit design, layout, prototypes, firmware, pilot run, production.<br />
* EDA electronic design automation software is a subset of CAD in general. Is there a wiki that discusses CAD in general? Until I find it, I'm going to post these tools here: "Google SketchUp is a powerful yet easy-to-learn 3D software tool" http://sketchup.google.com/ ; "Inkscape is the best tool for SVG standard vector graphics" http://wiki.inkscape.org/ ; Visual Wiki http://visualwiki.org/<br />
* [http://www.national.com/rap/Story/0,1562,18,00.html "What's All This Ground Noise Stuff, Anyhow?"] by Robert A. Pease<br />
* [http://www.elecdesign.com/Articles/ArticleID/6150/6150.html "What's All This Teflon Stuff, Anyhow?"] by Robert A. Pease -- explains a situation using lots of metal (instead of carefully insulating everything with lots of Teflon) causes less noise. Also mentions "why am I telling you all of these details? If I design a tester with greatly improved performance to help me test a really high-performance product, why should I tell all our competitors so that anybody in the world can test their products using the improved tester? Why should I give away all of these hard-earned secrets?" and gives some very good reasons.<br />
* [http://groups.google.to/group/sci.electronics.design/browse_thread/thread/889153f0e77b1718/fcaac532bb6d4b12?fwc=1 sci.electronics.design: EDN: Measuring Nanoamperes] discusses some ways to measure extremely small currents.<br />
* [http://www.millpcbs.com/ MillPCBs.com for techniques on using a small cnc machine to mill PCB's]<br />
* [http://groups.yahoo.com/group/Homebrew_PCBs yahoo.com/group/Homebrew_PCBs]<br />
* [http://www.electricstuff.co.uk/pcbs.html electricstuff.co.uk/pcbs]<br />
* [http://www.fullnet.com/~tomg/gooteepc.htm fullnet.com/~tomg/gooteepc]<br />
* The notion that through-hole soldering is easier than soldering surface-mount devices is, and always has been, [http://archives.seul.org/geda/user/Aug-2004/msg00175.html a myth.]<br />
* [http://www.instructables.com/id/Intro-into-SMD-Soldering/ Intro into SMD Soldering]<br />
* [http://PMinMO.com/ PMinMO.com is THE PLACE for DIY CNC driver information]<br />
<br />
== Environmental Issues ==<br />
<br />
see [[better for the environment]].<br />
<br />
<br />
[[Category:Techniques]]</div>Yanhttp://www.opencircuits.com/index.php?title=Programming_the_Device&diff=16644Programming the Device2008-10-21T03:16:01Z<p>Yan: /* Loading Firmware */ updated dsPic_Programmer.zip</p>
<hr />
<div>==Requirements==<br />
<br />
===Hardware===<br />
#PC with COM port (Windows XP Installed for MPLAB)<br />
#ICD2 Programmer<br />
#Target Board<br />
#5V Power Supply<br />
<br />
===Software===<br />
#[http://ww1.microchip.com/downloads/en/DeviceDoc/MP750.zip MPLAB IDE v7.50]: v7.60 is not compatible with our current [http://www.sure-electronics.com/ ICD2 Programmers]. There are consistent "Devices cannot be founded" warnings.<br />
#[http://chungyan5.no-ip.org/websvn/listing.php dsPicProgrammer] ('''dsPicProgrammer.jar''')<br />
<br />
===Files===<br />
#[http://chungyan5.no-ip.org/websvn/listing.php dsPicBootloader] ('''bl_5011.hex'''). Original assembly code by ingenia can be downloaded from [http://www.ingenia-cat.com/download/iBL.s here].<br />
#Application hex file (e.g. '''app.hex''')<br />
<br />
<br />
==Loading Bootloader (Once only)==<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Loading Bootloader<br />
! Step !! Remarks <br />
|-valign="top"<br />
| Install [http://ww1.microchip.com/downloads/en/DeviceDoc/MP750.zip MPLAB IDE] || <br />
*Do '''NOT''' connect ICD 2 (via USB) to PC<br />
*Execute '''MPLAB vX.XX Install.exe'''<br />
|-valign="top"<br />
| Install USB Driver ||<br />
*Follow the instruction in (C:\Program Files\Microchip\MPLAB IDE\ICD2\Drivers\Ddicd2.htm)<br />
|-valign="top"<br />
| Select Target Chip ||<br />
*Run MPLAB IDE on PC<br />
*Select: Configure>Select Devices...<br />
*Choose dsPIC30F5011<br />
|-valign="top"<br />
| Target <-> ICD 2 ||<br />
*Use six pin cable. Beware of the pin assignments. Only pin 1 - 5 should be used.<br />
*Place Jumper on target board (if any). The Jumper connects target V<sub>cc</sub> to ICD 2.<br />
*Do '''NOT''' power-up the target.<br />
|-valign="top"<br />
| ICD 2 <-> PC ||<br />
*Plug-in ICD 2 to PC via USB cable<br />
*Power-up the target.<br />
*Select: Programmer>Select Programmer>MPLAB ICD 2<br />
*If this is the first time the ICD 2 is connected to PC, MPLAB IDE will automatically download the required OS to ICD 2, wait until it has finished<br />
*If you have not connected and powered up the target, you might see Warnings on invalid device IDs, and/or running self tests.<br />
*See results of self test if necessary: Programmer>Settings, Status Tab. Refer to [http://ww1.microchip.com/downloads/en/DeviceDoc/51331B.pdf ICD2 User's Guide] Chapter 7.<br />
|-valign="top"<br />
| Load Bootloader ||<br />
*Select: File>Import...<br />
*Select '''bl_5011.hex'''<br />
|-valign="top"<br />
| Start Programming ||<br />
*Select: Programmer>Program<br />
|-valign="top"<br />
| Finishing ||<br />
*Power-down the Taget<br />
*Select: Programmer>Select Programmer>None<br />
*Unplug USB cable<br />
|-<br />
|}<br />
<br />
<br />
==Loading Firmware==<br />
*Download [http://chungyan5.no-ip.org/open_data/electronic_computer/platforms/dspic/dsPicProgrammer/dsPicProgrammer1.5.5.zip dsPic_Programmer.zip] or [http://chungyan5.no-ip.org/open_data/electronic_computer/platforms/dspic/dsPicProgrammer/dsPicProgrammer/ updated directory]<br />
*Save to a directory.<br />
::e.g. desktop<br />
*Unzip the dsPic_Programmer.zip, then you have an unziped file.<br />
[[Image:prog_guid_dl.JPG]]<br />
<br />
----<br />
<br />
*Drag the unzip file to a director.<br />
::eg. USB memory devics<br />
[[Image:prog_guid_drag.JPG]]<br />
<br />
----<br />
<br />
*Save your .hex file(foo.hex) to your directory location <br />
::e.g. X:\dsPic_Programmer\ ---> X:\ is the driver where the dsPic_Programmer located<br />
[[Image:prog_guid_hex.JPG]]<br />
===Download Firmware===<br />
*Start a Command Prompt<br />
**Start -> Run<br>[[Image:2 1 run.JPG]]<br><br />
**Enter cmd<br>[[Image:2 2 cmd.JPG]]<br><br />
*Run dsPicProgrammer<br />
**Make sure your device is connected through a "Direct RS232 Cable" to PC Serial Port. <br />
**Change to the directory where dsPicProgrammer.jar is located and run the command:<br />
***for example, jre\bin\java -Djava.library.path=.\rxtx\bin -jar dspicProgrammer.jar COM1 115200 foo.hex<br />
***Or directly using dsPicProgrammer.bat COM1 115200 foo.hex(Windows)<br />
***java -jar dsPicProgrammer.jar /dev/ttyS0 115200 foo.hex (Linux)<br />
:::where COM1 is your COM Port ID<br />
:::115200 is communication speed [in bps]<br />
:::foo.hex is your firmware new file<br />
::[[Image:2 3 command.JPG]]<br />
:*When the program prompt you for an input, press y:<br>[[Image:2 4 prompt.JPG]]<br><br />
:*If communication can be established, you should see something like this:<br>[[Image:2 5 progress.JPG]]<br><br />
:*Wait until programming is completed.<br>[[Image:2 6 complete.JPG]]<br><br />
:*after all completed, power OFF your device, then power ON again, enjoy your new updated.<br />
<br />
==Troubleshooting==<br />
===Invalid COM Port===<br />
*In case of selecting an invalid COM port, you should see the error message:<br>gnu.io.NoSuchPortException: Choosing COM Port Error<br>[[Image:3 1 com err.JPG]]<br><br><br />
===Missing firmware file===<br />
*In case of selecting a firmware file that does not exist, you should see the error message:<br>java.io.FileNotFoundException: foo1.hex <The system cannot find the file specified><br>[[Image:3 2 file err.JPG]]<br><br><br />
===Missing RXTX driver===<br />
*In case of missing the RXTX driver, you should see the error message:<br>Exception in thread “main” java.lang.NoClassDefFoundError: gnu/io/UnsupportedCommOperationException<br>[[Image:3 3 rxtx err.JPG]]<br><br></div>Yanhttp://www.opencircuits.com/index.php?title=Talk:GPIB&diff=16627Talk:GPIB2008-10-19T09:12:57Z<p>Yan: ans. gpib open hw, bf bd. & dspic bd.</p>
<hr />
<div>Is there any open-hardware device that uses GPIB?<br />
<br />
What is the "dspic33 board, bf1 board"?<br />
The [http://www.sparkfun.com/commerce/product_info.php?products_id=8438 SparkFun dsPIC33FJ256 board], as far as I can tell, does not have a GPIB interface.<br />
--[[User:DavidCary|DavidCary]] 06:29, 18 October 2008 (PDT)<br />
<br />
<br />
i just can answer, i have not found any open-hardware using GPIB until now. We are going to do that, but not urgent for me. I just write down and hope to begin in the future.<br />
<br />
dspic33 board is the our project [http://opencircuits.com/DsPIC30F_5011_Development_Board DsPIC30F 5011 Development Board]<br />
<br />
bf1 board is a blackfin board which we are going to run uClinux, i will post to opencircuits.com later <br />
<br />
--[[User:Yan|Yan]] 02:12, 19 October 2008 (PDT)</div>Yanhttp://www.opencircuits.com/index.php?title=Ethernet_Module&diff=16519Ethernet Module2008-10-03T04:27:15Z<p>Yan: /* ToDo List */ API in ethernet for other system to control our device</p>
<hr />
<div>==Introduction==<br />
*let a device have the following capabilities<br />
**can be controlled by a general browser in a desktop computer<br />
**access a server by itself to providing data, such as: device model no., serial no., any application data, or send out email for any events.<br />
*This project aims to develop an Ethernet Module, to be used in conjunction with a 8/16 bits embedded system such as the [http://opencircuits.com/DsPIC30F_5011_Development_Board dsPic33F development board].<br />
*[{{SERVER}}/Ethernet_Module#Architecture Architecture]<br />
<br />
==Bug List==<br />
*DHCP<br />
**dhcp client fault from buffalo router<br />
**occasionally cannot access webserver with dhcp<br />
<br />
*DHCP<br />
**dhcp client fault from main router<br />
**occasionally cannot access webserver with dhcp<br />
**possible cause: module tries to get IP configuration when switching on and off too frequently. This causes the router to enter into an unknown state. Even using the static mode with the same IP cannot get Internet access properly. When wait for some time and switch on the module again, the router may have been "reset", and the connection is ok again.<br />
<br />
<br />
==ToDo List==<br />
*32kB constant limitations<br />
**see if webserver can be stored in flash in file system<br />
*[{{SERVER}}/Ethernet_Module#SNMP_Agent SNMP]<br />
**porting snmp to uip<br />
**reference to lwip<br />
**a API(or any method) to let other system to talk to our device OR by scpi, modbus<br />
*SMTP<br />
**some router cannot used SMTP module<br />
**the router return its own IP as DNS resolver, and it does support only parsing direct IP function<br />
**desktop applications (e.g. outlook, thunderbird, webmail) do not use DNS resolver (UDP application) to connect to the mail server, but use TCP/IP to do the job<br />
*https by SSL<br />
**on chip SSL(more faster) OR software SSL(need to upgrade CPU power to process the calculation)<br />
**reference - http://www.networkworld.com/news/tech/2002/0729tech.html<br />
<br />
==Hardware==<br />
===Component List===<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
! Special Item !! Description !! Quantity<br />
|-valign="top"<br />
| [http://www.davicom.com.tw/big5/download/Data%20Sheet/DM9000A-DS-F01-101906.pdf DM9000AEP] || Ethernet Controller from [http://www.davicom.com.tw/eng/index.htm Davicom] || 1<br />
|-<br />
| [http://www.hanrun.com/hr/upfile/2_1_113.pdf HR911102A] || RJ45 Connector with Integrated Magnetics for 10/100 Base-TX || 1<br />
|-<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/21749F.pdf 93LC46B-I/SN] || 1K Serial EEPROM || 1 (Optional)<br />
|-<br />
| 25MHz Crystal || Crystal || 1<br />
|-<br />
| 22pF || For Crystal Use || 2<br />
|-<br />
| 220uF || For RXVDD25/TXVDD25 || 1<br />
|-<br />
| 49.9ohm || For RX+/RX-/TX+/TX- || 4<br />
|-<br />
| 6.8kohm || For BGRES/BGGND || 1<br />
|-<br />
| 510ohm || For LEDs|| 2<br />
|-<br />
|}<br />
<br />
===Circuit and PCB===<br />
in [http://chungyan5.no-ip.org/vc/?root=ethernet gEDA format]<br />
and its gEDA [http://www.opencircuits.com/PCB_Footprints#gEDA_Symbols_and_footprints sym and footprints]<br />
<br />
<br />
==Software Driver==<br />
*Download [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/dm9000a.c?root=freertos_posix&view=markup dm9000a.c]<br />
*Download [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/include/dm9000a.h?root=freertos_posix&view=markup dm9000a.h]<br />
*Base on [http://www.freertos.org/ FreeRTOS] and [http://opencircuits.com/DsPIC30F_5011_Development_Board dsPIC33 platform]<br />
*Using POSIX-like API:<br />
**'''int dmfe_open(int flags)''': initialize the Ethernet controller for 10MHz Half-Duplex<br />
**'''int dmfe_close()''': turn off the PHY layer<br />
**'''int dmfe_read(void)''': copy a packet to the default buffer<br />
**'''int dmfe_write(unsigned char device, unsigned char *buf, int count)''': copy count bytes of the data from buf and transmit<br />
**'''void dmfe_interrupt(void)''': process the transmit interrupt from DM9000A<br />
<br />
<br />
==TCP/IP Stack==<br />
*uIP and lwIP are light weight TCP/IP Stack designed for 8-bit/16-bit embedded systems.<br />
<br />
----<br />
<br />
===uIP===<br />
*Develped by Adam Dunkels of the Networked Embedded Systems group at the Swedish Institute of Computer Science.<br />
*[http://www.sics.se/~adam/uip/ uIP] is under the [http://www.sics.se/~adam/uip/index.php/License BSD-style license]<br />
====CVS Repository====<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
! Attribute !! Value<br />
|-valign="top"<br />
| Host || uip-stack.cvs.sourceforge.net<br />
|-<br />
| Repository Path || /cvsroot/uip-stack<br />
|-<br />
| Connection Type || pserver<br />
|-<br />
| User || anonymous<br />
|-<br />
|}<br />
*Changes made to CVS Repository (tag: HEAD v1.1)<br />
**'''uip.c'''<br />
***Comment out all DEBUG_PRINTF(...) in lines 1, 323, 910, 1015, 1070, 1863, 1868, 1869<br />
**'''uip.h'''<br />
***Change line 1070 to<br># define HTONS(n) (u16_t)(((((u16_t) (n)) << 8)&0xff00) | ((((u16_t) (n)) >> 8)&0x00ff))<br />
**'''psock.c'''<br />
***Change line 188 to<br>s->sendptr = (u8_t*) buf;<br />
***Change lines 276, 303 to<br>buf_setup(&psock->buf, (u8_t*)(psock->bufptr), psock->bufsize);<br />
***Change line 334 to<br>buf_setup(&psock->buf, (u8_t*)buffer, buffersize);<br />
<br />
====Porting====<br />
*Include the following files to use the uIP stack<br />
**timer.c<br />
**uip.c<br />
**uip_arp.c<br />
**psock.c<br />
*The following files have been created to port uIP 1.0 to dsPic33F development board using FreeRTOS<br />
*[http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/clock-arch.c?root=freertos_posix&view=markup clock-arch.c]: return the os tick counts since the system is turned on.<br />
*[http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/include/clock-arch.h?root=freertos_posix&view=markup clock-arch.h]: a constant specifying the number of os ticks in one second.<br />
*[http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/dspic33/rackmount/04_uip/include/uip-conf.h?root=freertos_posix&view=markup uip-config.h]: configuration for your application.<br />
<br />
----<br />
<br />
===lwIP===<br />
*[http://savannah.nongnu.org/projects/lwip/ lwIP] is a small independent implementation of uIP.<br />
*It is more powerful than uIP but requires more memory.<br />
*lwIP is under the [http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5 Modified BSD License]<br />
====CVS Repository====<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
! Attribute !! Value<br />
|-valign="top"<br />
| Host || cvs.savannah.nongnu.org<br />
|-<br />
| Repository Path || /sources/lwip<br />
|-<br />
| Connection Type || pserver<br />
|-<br />
| User || anonymous<br />
|-<br />
|}<br />
====Porting====<br />
*To be added<br />
<br />
<br />
==uIP Ethernet Application==<br />
<br />
===DHCP Client===<br />
*Enable UDP in "uip-config.h"<br />
#define UIP_CONF_UDP 1<br />
*Make sure your uip buffer size is large enough (DHCP messages from some servers can be more than 500 bytes). In my setting, I use 1536 in "uip-config.h"<br />
#define UIP_CONF_BUFFER_SIZE 1536<br />
*Include the dhcpc.h header file in "uip-config.h"<br />
#include "dhcpc.h"<br />
*Change PT_WAIT_UNTIL(...) to PT_YIELD_UNTIL(...) in line 259 and 276 in "dhcpc.c" [This is a known bug in dhcpc.c]<br />
*In your main loop, initialize your MAC address and DHCP if UIP_FIXEDADDR is 0 in "uip-opt.h", for example:<br />
int main(void)<br />
{<br />
uip_ipaddr_t ipaddr;<br />
struct timer periodic_timer, arp_timer;<br />
struct uip_eth_addr mac = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06};<br />
<br />
timer_set(&periodic_timer, CLOCK_SECOND / 2);<br />
timer_set(&arp_timer, CLOCK_SECOND * 10);<br />
<br />
tapdev_init();<br />
uip_init();<br />
<br />
uip_setethaddr(mac);<br />
dhcpc_init(&mac, 6);<br />
<br />
while(1){<br />
//normal codes goes here<br />
}<br />
}<br />
*Implement dhcpc_configured(). This function will be called after DHCP client has obtained an IP address. Basically, you have to at least set your IP address, subnet mask and default gateway, for example,<br />
void dhcpc_configured(const struct dhcpc_state *s)<br />
{<br />
uip_sethostaddr(s->ipaddr);<br />
uip_setnetmask(s->netmask);<br />
uip_setdraddr(s->default_router);<br />
<br />
//you can print your ip addr to your console/lcd to see if you get a valid ip address<br />
}<br />
*An example of using DHCP Client in the dsPic33F development board can be found [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/common/app_http.c?root=freertos_posix&view=markup here].<br />
<br />
===Web Server===<br />
*Include the "webserver.h" header file in "uip-config.h"<br />
#include "webserver.h"<br />
*Modify httpd-fs.h<br />
**HTTPD_FS_STATISTICS set to 0<br />
*Create a website using HTML tags with/without Javascript<br />
*Modify httpd-fs.c<br />
**changed #include "httpd-fsdata.c" to #include <httpd-fsdata.c> <br />
*Generate httpd-fsdata.c for your website by executing '''perl makefsdata''' under your web root directory.<br />
====add-on====<br />
*The Web Server included in uIP 1.0 has been designed to load/reload the entire page (either html/shtml files) in response to a HTTP GET command, e.g.<br />
GET /index.html HTTP/1.1<br />
GET /abc.shtml HTTP/1.1<br />
*As a result, if the webpage is required to refresh the dynamic data periodically, the surfing experience will be degraded by the large transfer of datastream.<br />
*In consideration of the above issue, a solution is proposed here, so that the webserver can handle this kind of cgi HTTP-request<br />
GET /abc.shtml?val=500.0&button=Set HTTP/1.1<br />
*Modify httpd.c<br />
**added #include "httpd-hget.h" in line 63<br />
**added httpd_hget(s->filename) in line 224<br />
*Create httpd-hget.h<br />
**added to generate dynamic pages, e.g. /abc.shtml?button=Refresh<br />
#ifndef __HTTPD_HGET_H__<br />
#define __HTTPD_HGET_H__<br />
extern void httpd_hget(char *name);<br />
#endif<br />
*Create httpd-hget.c<br />
**an example is shown [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/dspic33/rackmount/04_uip/uip/httpd-hget.c?root=freertos_posix&view=markup here]<br />
<br />
==SNMP Agent==<br />
*Simple Network Management Protocol (SNMP) is a standard protocol to access variables to remote device via the Internet. Reference in [http://en.wikipedia.org/wiki/Simple_Network_Management_Protocol wikipedia.org]<br />
*It belongs to the Application Layer, as in HTTP.<br />
*If a device is SNMP compatible, any SNMP compatible host system can monitor and control that device.<br />
<br />
===Components in a SNMP System===<br />
*Network Management Station (NMS)<br />
**This is a client, initiating SNMP communication.<br />
**This can be a PC with an NMS software (e.g. [http://nino.sourceforge.net/nino/index.html NINO]), polling data from the SNMP agents periodically.<br />
*SNMP Agents<br />
**These are servers, responding to one or multiple NMS requests.<br />
*Management Information Base (MIB)<br />
**A special collection of variables managed by the SNMP agents.<br />
**MIB has a tree-like structure.<br />
**An Object Identifier (OID) is given for each node.<br />
**Data are stored at the end-nodes.<br />
**Private variables may be constructed under the "enterprise" sub-tree.<br />
**The OID for "enterprise" can be obtained from [http://www.iana.org/cgi-bin/enterprise.pl Internet Assigned Number Authority (IANA)].<br />
<br />
===Abstract Syntax Notation===<br />
*Each MIB variable contains several attributes, such as data type, access type and object identifier.<br />
*Abstract Syntax Notation version 1 (ASN.1) is a language to define these attributes in SNMP.<br />
<br />
==Architecture==<br />
+---------------------------------------------+--------------------+-------+<br />
Applications | Ethernet Application | GUI Application | ... |<br />
+--------+------+------+----------+------+----+ | |<br />
Web Libraries | Web | DHCP | SNMP | DNS | SMTP |... | | |<br />
| Server | | | Resolver | | | | |<br />
+--------+------+------+----------+------+----+ | |<br />
Socket API | Linux-like Socket | | |<br />
+---------------------------------------------+ | |<br />
TCP/IP Stack | uip | | |<br />
+---------------------------------------------+ | |<br />
| Ethernet Controller | | |<br />
+--------------------------------------+------+--------------------+-------+<br />
POSIX API | POSIX System Calls | POSIX Threads |<br />
+--------------------------------------+-----------------------------------+<br />
| Drivers | Task Scheduler |<br />
+--------------------------------------+-----------------------------------+<br />
<br />
==Reference==<br />
===DM9000A===<br />
*[http://www.davicom.com.tw/eng/products/dm9000a.htm DM9000A Description]<br />
*[http://www.davicom.com.tw/big5/download/Data%20Sheet/DM9000A-DS-F01-101906.pdf DM9000A Datasheet]<br />
*[http://www.davicom.com.tw/big5/download/AC/dm9000a/DM9000A%20circuit_EMI_052306.pdf Application Circuit]<br />
*[http://www.davicom.com.tw/big5/download/LayoutGuide/DM9000A_9010-LG-V11_031706.pdf Layout Guidelines]<br />
*[http://www.davicom.com.tw/big5/download/ApplicationNote/DM9000A%20Application%20Notes%20Ver%201_20_101906.pdf Application Note]<br />
*[http://www.davicom.com.tw/eng/download/Driver/driver_9000.htm DM9000A Official Drivers]<br />
===dsPic33F Development Board===<br />
*[http://opencircuits.com/DsPIC30F_5011_Development_Board dsPic33F Development Board]<br />
===uIP===<br />
*[http://www.sics.se/~adam/uip/index.php/Main_Page uIP Description]<br />
*[http://www.sics.se/~adam/uip/index.php/Documentation uIP Documentation]<br />
*[http://www.sics.se/~adam/uip/index.php/Download Download]<br />
*[http://sourceforge.net/cvs/?group_id=186227 CVS Repository]<br />
===lwIP===<br />
*[http://savannah.nongnu.org/projects/lwip/ lwIP Description]<br />
*[http://www.nongnu.org/lwip/ Documentation]<br />
===HTML===<br />
*[http://www.w3schools.com/default.asp W3 Schools]: Learning how to write HTML and JavaScript<br />
*[http://www.nvu.com/index.php Nvu]: Open source HTML Editor<br />
===SNMP===<br />
*[http://www.snmplink.org SNMP Link]: Information on SNMP Agents<br />
*[http://pen.iana.org/pen/PenApplication.page IANA]: Applying a Private Enterprise Number</div>Yanhttp://www.opencircuits.com/index.php?title=Ethernet_Module&diff=16518Ethernet Module2008-10-03T04:24:02Z<p>Yan: /* SNMP Agent */ wikipedia.org reference</p>
<hr />
<div>==Introduction==<br />
*let a device have the following capabilities<br />
**can be controlled by a general browser in a desktop computer<br />
**access a server by itself to providing data, such as: device model no., serial no., any application data, or send out email for any events.<br />
*This project aims to develop an Ethernet Module, to be used in conjunction with a 8/16 bits embedded system such as the [http://opencircuits.com/DsPIC30F_5011_Development_Board dsPic33F development board].<br />
*[{{SERVER}}/Ethernet_Module#Architecture Architecture]<br />
<br />
==Bug List==<br />
*DHCP<br />
**dhcp client fault from buffalo router<br />
**occasionally cannot access webserver with dhcp<br />
<br />
*DHCP<br />
**dhcp client fault from main router<br />
**occasionally cannot access webserver with dhcp<br />
**possible cause: module tries to get IP configuration when switching on and off too frequently. This causes the router to enter into an unknown state. Even using the static mode with the same IP cannot get Internet access properly. When wait for some time and switch on the module again, the router may have been "reset", and the connection is ok again.<br />
<br />
<br />
==ToDo List==<br />
*32kB constant limitations<br />
**see if webserver can be stored in flash in file system<br />
*[{{SERVER}}/Ethernet_Module#SNMP_Agent SNMP]<br />
**porting snmp to uip<br />
**reference to lwip<br />
*SMTP<br />
**some router cannot used SMTP module<br />
**the router return its own IP as DNS resolver, and it does support only parsing direct IP function<br />
**desktop applications (e.g. outlook, thunderbird, webmail) do not use DNS resolver (UDP application) to connect to the mail server, but use TCP/IP to do the job<br />
*https by SSL<br />
**on chip SSL(more faster) OR software SSL(need to upgrade CPU power to process the calculation)<br />
**reference - http://www.networkworld.com/news/tech/2002/0729tech.html<br />
<br />
==Hardware==<br />
===Component List===<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
! Special Item !! Description !! Quantity<br />
|-valign="top"<br />
| [http://www.davicom.com.tw/big5/download/Data%20Sheet/DM9000A-DS-F01-101906.pdf DM9000AEP] || Ethernet Controller from [http://www.davicom.com.tw/eng/index.htm Davicom] || 1<br />
|-<br />
| [http://www.hanrun.com/hr/upfile/2_1_113.pdf HR911102A] || RJ45 Connector with Integrated Magnetics for 10/100 Base-TX || 1<br />
|-<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/21749F.pdf 93LC46B-I/SN] || 1K Serial EEPROM || 1 (Optional)<br />
|-<br />
| 25MHz Crystal || Crystal || 1<br />
|-<br />
| 22pF || For Crystal Use || 2<br />
|-<br />
| 220uF || For RXVDD25/TXVDD25 || 1<br />
|-<br />
| 49.9ohm || For RX+/RX-/TX+/TX- || 4<br />
|-<br />
| 6.8kohm || For BGRES/BGGND || 1<br />
|-<br />
| 510ohm || For LEDs|| 2<br />
|-<br />
|}<br />
<br />
===Circuit and PCB===<br />
in [http://chungyan5.no-ip.org/vc/?root=ethernet gEDA format]<br />
and its gEDA [http://www.opencircuits.com/PCB_Footprints#gEDA_Symbols_and_footprints sym and footprints]<br />
<br />
<br />
==Software Driver==<br />
*Download [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/dm9000a.c?root=freertos_posix&view=markup dm9000a.c]<br />
*Download [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/include/dm9000a.h?root=freertos_posix&view=markup dm9000a.h]<br />
*Base on [http://www.freertos.org/ FreeRTOS] and [http://opencircuits.com/DsPIC30F_5011_Development_Board dsPIC33 platform]<br />
*Using POSIX-like API:<br />
**'''int dmfe_open(int flags)''': initialize the Ethernet controller for 10MHz Half-Duplex<br />
**'''int dmfe_close()''': turn off the PHY layer<br />
**'''int dmfe_read(void)''': copy a packet to the default buffer<br />
**'''int dmfe_write(unsigned char device, unsigned char *buf, int count)''': copy count bytes of the data from buf and transmit<br />
**'''void dmfe_interrupt(void)''': process the transmit interrupt from DM9000A<br />
<br />
<br />
==TCP/IP Stack==<br />
*uIP and lwIP are light weight TCP/IP Stack designed for 8-bit/16-bit embedded systems.<br />
<br />
----<br />
<br />
===uIP===<br />
*Develped by Adam Dunkels of the Networked Embedded Systems group at the Swedish Institute of Computer Science.<br />
*[http://www.sics.se/~adam/uip/ uIP] is under the [http://www.sics.se/~adam/uip/index.php/License BSD-style license]<br />
====CVS Repository====<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
! Attribute !! Value<br />
|-valign="top"<br />
| Host || uip-stack.cvs.sourceforge.net<br />
|-<br />
| Repository Path || /cvsroot/uip-stack<br />
|-<br />
| Connection Type || pserver<br />
|-<br />
| User || anonymous<br />
|-<br />
|}<br />
*Changes made to CVS Repository (tag: HEAD v1.1)<br />
**'''uip.c'''<br />
***Comment out all DEBUG_PRINTF(...) in lines 1, 323, 910, 1015, 1070, 1863, 1868, 1869<br />
**'''uip.h'''<br />
***Change line 1070 to<br># define HTONS(n) (u16_t)(((((u16_t) (n)) << 8)&0xff00) | ((((u16_t) (n)) >> 8)&0x00ff))<br />
**'''psock.c'''<br />
***Change line 188 to<br>s->sendptr = (u8_t*) buf;<br />
***Change lines 276, 303 to<br>buf_setup(&psock->buf, (u8_t*)(psock->bufptr), psock->bufsize);<br />
***Change line 334 to<br>buf_setup(&psock->buf, (u8_t*)buffer, buffersize);<br />
<br />
====Porting====<br />
*Include the following files to use the uIP stack<br />
**timer.c<br />
**uip.c<br />
**uip_arp.c<br />
**psock.c<br />
*The following files have been created to port uIP 1.0 to dsPic33F development board using FreeRTOS<br />
*[http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/clock-arch.c?root=freertos_posix&view=markup clock-arch.c]: return the os tick counts since the system is turned on.<br />
*[http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/include/clock-arch.h?root=freertos_posix&view=markup clock-arch.h]: a constant specifying the number of os ticks in one second.<br />
*[http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/dspic33/rackmount/04_uip/include/uip-conf.h?root=freertos_posix&view=markup uip-config.h]: configuration for your application.<br />
<br />
----<br />
<br />
===lwIP===<br />
*[http://savannah.nongnu.org/projects/lwip/ lwIP] is a small independent implementation of uIP.<br />
*It is more powerful than uIP but requires more memory.<br />
*lwIP is under the [http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5 Modified BSD License]<br />
====CVS Repository====<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
! Attribute !! Value<br />
|-valign="top"<br />
| Host || cvs.savannah.nongnu.org<br />
|-<br />
| Repository Path || /sources/lwip<br />
|-<br />
| Connection Type || pserver<br />
|-<br />
| User || anonymous<br />
|-<br />
|}<br />
====Porting====<br />
*To be added<br />
<br />
<br />
==uIP Ethernet Application==<br />
<br />
===DHCP Client===<br />
*Enable UDP in "uip-config.h"<br />
#define UIP_CONF_UDP 1<br />
*Make sure your uip buffer size is large enough (DHCP messages from some servers can be more than 500 bytes). In my setting, I use 1536 in "uip-config.h"<br />
#define UIP_CONF_BUFFER_SIZE 1536<br />
*Include the dhcpc.h header file in "uip-config.h"<br />
#include "dhcpc.h"<br />
*Change PT_WAIT_UNTIL(...) to PT_YIELD_UNTIL(...) in line 259 and 276 in "dhcpc.c" [This is a known bug in dhcpc.c]<br />
*In your main loop, initialize your MAC address and DHCP if UIP_FIXEDADDR is 0 in "uip-opt.h", for example:<br />
int main(void)<br />
{<br />
uip_ipaddr_t ipaddr;<br />
struct timer periodic_timer, arp_timer;<br />
struct uip_eth_addr mac = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06};<br />
<br />
timer_set(&periodic_timer, CLOCK_SECOND / 2);<br />
timer_set(&arp_timer, CLOCK_SECOND * 10);<br />
<br />
tapdev_init();<br />
uip_init();<br />
<br />
uip_setethaddr(mac);<br />
dhcpc_init(&mac, 6);<br />
<br />
while(1){<br />
//normal codes goes here<br />
}<br />
}<br />
*Implement dhcpc_configured(). This function will be called after DHCP client has obtained an IP address. Basically, you have to at least set your IP address, subnet mask and default gateway, for example,<br />
void dhcpc_configured(const struct dhcpc_state *s)<br />
{<br />
uip_sethostaddr(s->ipaddr);<br />
uip_setnetmask(s->netmask);<br />
uip_setdraddr(s->default_router);<br />
<br />
//you can print your ip addr to your console/lcd to see if you get a valid ip address<br />
}<br />
*An example of using DHCP Client in the dsPic33F development board can be found [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/common/app_http.c?root=freertos_posix&view=markup here].<br />
<br />
===Web Server===<br />
*Include the "webserver.h" header file in "uip-config.h"<br />
#include "webserver.h"<br />
*Modify httpd-fs.h<br />
**HTTPD_FS_STATISTICS set to 0<br />
*Create a website using HTML tags with/without Javascript<br />
*Modify httpd-fs.c<br />
**changed #include "httpd-fsdata.c" to #include <httpd-fsdata.c> <br />
*Generate httpd-fsdata.c for your website by executing '''perl makefsdata''' under your web root directory.<br />
====add-on====<br />
*The Web Server included in uIP 1.0 has been designed to load/reload the entire page (either html/shtml files) in response to a HTTP GET command, e.g.<br />
GET /index.html HTTP/1.1<br />
GET /abc.shtml HTTP/1.1<br />
*As a result, if the webpage is required to refresh the dynamic data periodically, the surfing experience will be degraded by the large transfer of datastream.<br />
*In consideration of the above issue, a solution is proposed here, so that the webserver can handle this kind of cgi HTTP-request<br />
GET /abc.shtml?val=500.0&button=Set HTTP/1.1<br />
*Modify httpd.c<br />
**added #include "httpd-hget.h" in line 63<br />
**added httpd_hget(s->filename) in line 224<br />
*Create httpd-hget.h<br />
**added to generate dynamic pages, e.g. /abc.shtml?button=Refresh<br />
#ifndef __HTTPD_HGET_H__<br />
#define __HTTPD_HGET_H__<br />
extern void httpd_hget(char *name);<br />
#endif<br />
*Create httpd-hget.c<br />
**an example is shown [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/dspic33/rackmount/04_uip/uip/httpd-hget.c?root=freertos_posix&view=markup here]<br />
<br />
==SNMP Agent==<br />
*Simple Network Management Protocol (SNMP) is a standard protocol to access variables to remote device via the Internet. Reference in [http://en.wikipedia.org/wiki/Simple_Network_Management_Protocol wikipedia.org]<br />
*It belongs to the Application Layer, as in HTTP.<br />
*If a device is SNMP compatible, any SNMP compatible host system can monitor and control that device.<br />
<br />
===Components in a SNMP System===<br />
*Network Management Station (NMS)<br />
**This is a client, initiating SNMP communication.<br />
**This can be a PC with an NMS software (e.g. [http://nino.sourceforge.net/nino/index.html NINO]), polling data from the SNMP agents periodically.<br />
*SNMP Agents<br />
**These are servers, responding to one or multiple NMS requests.<br />
*Management Information Base (MIB)<br />
**A special collection of variables managed by the SNMP agents.<br />
**MIB has a tree-like structure.<br />
**An Object Identifier (OID) is given for each node.<br />
**Data are stored at the end-nodes.<br />
**Private variables may be constructed under the "enterprise" sub-tree.<br />
**The OID for "enterprise" can be obtained from [http://www.iana.org/cgi-bin/enterprise.pl Internet Assigned Number Authority (IANA)].<br />
<br />
===Abstract Syntax Notation===<br />
*Each MIB variable contains several attributes, such as data type, access type and object identifier.<br />
*Abstract Syntax Notation version 1 (ASN.1) is a language to define these attributes in SNMP.<br />
<br />
==Architecture==<br />
+---------------------------------------------+--------------------+-------+<br />
Applications | Ethernet Application | GUI Application | ... |<br />
+--------+------+------+----------+------+----+ | |<br />
Web Libraries | Web | DHCP | SNMP | DNS | SMTP |... | | |<br />
| Server | | | Resolver | | | | |<br />
+--------+------+------+----------+------+----+ | |<br />
Socket API | Linux-like Socket | | |<br />
+---------------------------------------------+ | |<br />
TCP/IP Stack | uip | | |<br />
+---------------------------------------------+ | |<br />
| Ethernet Controller | | |<br />
+--------------------------------------+------+--------------------+-------+<br />
POSIX API | POSIX System Calls | POSIX Threads |<br />
+--------------------------------------+-----------------------------------+<br />
| Drivers | Task Scheduler |<br />
+--------------------------------------+-----------------------------------+<br />
<br />
==Reference==<br />
===DM9000A===<br />
*[http://www.davicom.com.tw/eng/products/dm9000a.htm DM9000A Description]<br />
*[http://www.davicom.com.tw/big5/download/Data%20Sheet/DM9000A-DS-F01-101906.pdf DM9000A Datasheet]<br />
*[http://www.davicom.com.tw/big5/download/AC/dm9000a/DM9000A%20circuit_EMI_052306.pdf Application Circuit]<br />
*[http://www.davicom.com.tw/big5/download/LayoutGuide/DM9000A_9010-LG-V11_031706.pdf Layout Guidelines]<br />
*[http://www.davicom.com.tw/big5/download/ApplicationNote/DM9000A%20Application%20Notes%20Ver%201_20_101906.pdf Application Note]<br />
*[http://www.davicom.com.tw/eng/download/Driver/driver_9000.htm DM9000A Official Drivers]<br />
===dsPic33F Development Board===<br />
*[http://opencircuits.com/DsPIC30F_5011_Development_Board dsPic33F Development Board]<br />
===uIP===<br />
*[http://www.sics.se/~adam/uip/index.php/Main_Page uIP Description]<br />
*[http://www.sics.se/~adam/uip/index.php/Documentation uIP Documentation]<br />
*[http://www.sics.se/~adam/uip/index.php/Download Download]<br />
*[http://sourceforge.net/cvs/?group_id=186227 CVS Repository]<br />
===lwIP===<br />
*[http://savannah.nongnu.org/projects/lwip/ lwIP Description]<br />
*[http://www.nongnu.org/lwip/ Documentation]<br />
===HTML===<br />
*[http://www.w3schools.com/default.asp W3 Schools]: Learning how to write HTML and JavaScript<br />
*[http://www.nvu.com/index.php Nvu]: Open source HTML Editor<br />
===SNMP===<br />
*[http://www.snmplink.org SNMP Link]: Information on SNMP Agents<br />
*[http://pen.iana.org/pen/PenApplication.page IANA]: Applying a Private Enterprise Number</div>Yanhttp://www.opencircuits.com/index.php?title=Ethernet_Module&diff=16517Ethernet Module2008-10-03T04:21:29Z<p>Yan: /* ToDo List */ give a link for snmp</p>
<hr />
<div>==Introduction==<br />
*let a device have the following capabilities<br />
**can be controlled by a general browser in a desktop computer<br />
**access a server by itself to providing data, such as: device model no., serial no., any application data, or send out email for any events.<br />
*This project aims to develop an Ethernet Module, to be used in conjunction with a 8/16 bits embedded system such as the [http://opencircuits.com/DsPIC30F_5011_Development_Board dsPic33F development board].<br />
*[{{SERVER}}/Ethernet_Module#Architecture Architecture]<br />
<br />
==Bug List==<br />
*DHCP<br />
**dhcp client fault from buffalo router<br />
**occasionally cannot access webserver with dhcp<br />
<br />
*DHCP<br />
**dhcp client fault from main router<br />
**occasionally cannot access webserver with dhcp<br />
**possible cause: module tries to get IP configuration when switching on and off too frequently. This causes the router to enter into an unknown state. Even using the static mode with the same IP cannot get Internet access properly. When wait for some time and switch on the module again, the router may have been "reset", and the connection is ok again.<br />
<br />
<br />
==ToDo List==<br />
*32kB constant limitations<br />
**see if webserver can be stored in flash in file system<br />
*[{{SERVER}}/Ethernet_Module#SNMP_Agent SNMP]<br />
**porting snmp to uip<br />
**reference to lwip<br />
*SMTP<br />
**some router cannot used SMTP module<br />
**the router return its own IP as DNS resolver, and it does support only parsing direct IP function<br />
**desktop applications (e.g. outlook, thunderbird, webmail) do not use DNS resolver (UDP application) to connect to the mail server, but use TCP/IP to do the job<br />
*https by SSL<br />
**on chip SSL(more faster) OR software SSL(need to upgrade CPU power to process the calculation)<br />
**reference - http://www.networkworld.com/news/tech/2002/0729tech.html<br />
<br />
==Hardware==<br />
===Component List===<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
! Special Item !! Description !! Quantity<br />
|-valign="top"<br />
| [http://www.davicom.com.tw/big5/download/Data%20Sheet/DM9000A-DS-F01-101906.pdf DM9000AEP] || Ethernet Controller from [http://www.davicom.com.tw/eng/index.htm Davicom] || 1<br />
|-<br />
| [http://www.hanrun.com/hr/upfile/2_1_113.pdf HR911102A] || RJ45 Connector with Integrated Magnetics for 10/100 Base-TX || 1<br />
|-<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/21749F.pdf 93LC46B-I/SN] || 1K Serial EEPROM || 1 (Optional)<br />
|-<br />
| 25MHz Crystal || Crystal || 1<br />
|-<br />
| 22pF || For Crystal Use || 2<br />
|-<br />
| 220uF || For RXVDD25/TXVDD25 || 1<br />
|-<br />
| 49.9ohm || For RX+/RX-/TX+/TX- || 4<br />
|-<br />
| 6.8kohm || For BGRES/BGGND || 1<br />
|-<br />
| 510ohm || For LEDs|| 2<br />
|-<br />
|}<br />
<br />
===Circuit and PCB===<br />
in [http://chungyan5.no-ip.org/vc/?root=ethernet gEDA format]<br />
and its gEDA [http://www.opencircuits.com/PCB_Footprints#gEDA_Symbols_and_footprints sym and footprints]<br />
<br />
<br />
==Software Driver==<br />
*Download [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/dm9000a.c?root=freertos_posix&view=markup dm9000a.c]<br />
*Download [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/include/dm9000a.h?root=freertos_posix&view=markup dm9000a.h]<br />
*Base on [http://www.freertos.org/ FreeRTOS] and [http://opencircuits.com/DsPIC30F_5011_Development_Board dsPIC33 platform]<br />
*Using POSIX-like API:<br />
**'''int dmfe_open(int flags)''': initialize the Ethernet controller for 10MHz Half-Duplex<br />
**'''int dmfe_close()''': turn off the PHY layer<br />
**'''int dmfe_read(void)''': copy a packet to the default buffer<br />
**'''int dmfe_write(unsigned char device, unsigned char *buf, int count)''': copy count bytes of the data from buf and transmit<br />
**'''void dmfe_interrupt(void)''': process the transmit interrupt from DM9000A<br />
<br />
<br />
==TCP/IP Stack==<br />
*uIP and lwIP are light weight TCP/IP Stack designed for 8-bit/16-bit embedded systems.<br />
<br />
----<br />
<br />
===uIP===<br />
*Develped by Adam Dunkels of the Networked Embedded Systems group at the Swedish Institute of Computer Science.<br />
*[http://www.sics.se/~adam/uip/ uIP] is under the [http://www.sics.se/~adam/uip/index.php/License BSD-style license]<br />
====CVS Repository====<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
! Attribute !! Value<br />
|-valign="top"<br />
| Host || uip-stack.cvs.sourceforge.net<br />
|-<br />
| Repository Path || /cvsroot/uip-stack<br />
|-<br />
| Connection Type || pserver<br />
|-<br />
| User || anonymous<br />
|-<br />
|}<br />
*Changes made to CVS Repository (tag: HEAD v1.1)<br />
**'''uip.c'''<br />
***Comment out all DEBUG_PRINTF(...) in lines 1, 323, 910, 1015, 1070, 1863, 1868, 1869<br />
**'''uip.h'''<br />
***Change line 1070 to<br># define HTONS(n) (u16_t)(((((u16_t) (n)) << 8)&0xff00) | ((((u16_t) (n)) >> 8)&0x00ff))<br />
**'''psock.c'''<br />
***Change line 188 to<br>s->sendptr = (u8_t*) buf;<br />
***Change lines 276, 303 to<br>buf_setup(&psock->buf, (u8_t*)(psock->bufptr), psock->bufsize);<br />
***Change line 334 to<br>buf_setup(&psock->buf, (u8_t*)buffer, buffersize);<br />
<br />
====Porting====<br />
*Include the following files to use the uIP stack<br />
**timer.c<br />
**uip.c<br />
**uip_arp.c<br />
**psock.c<br />
*The following files have been created to port uIP 1.0 to dsPic33F development board using FreeRTOS<br />
*[http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/clock-arch.c?root=freertos_posix&view=markup clock-arch.c]: return the os tick counts since the system is turned on.<br />
*[http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/include/clock-arch.h?root=freertos_posix&view=markup clock-arch.h]: a constant specifying the number of os ticks in one second.<br />
*[http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/dspic33/rackmount/04_uip/include/uip-conf.h?root=freertos_posix&view=markup uip-config.h]: configuration for your application.<br />
<br />
----<br />
<br />
===lwIP===<br />
*[http://savannah.nongnu.org/projects/lwip/ lwIP] is a small independent implementation of uIP.<br />
*It is more powerful than uIP but requires more memory.<br />
*lwIP is under the [http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5 Modified BSD License]<br />
====CVS Repository====<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
! Attribute !! Value<br />
|-valign="top"<br />
| Host || cvs.savannah.nongnu.org<br />
|-<br />
| Repository Path || /sources/lwip<br />
|-<br />
| Connection Type || pserver<br />
|-<br />
| User || anonymous<br />
|-<br />
|}<br />
====Porting====<br />
*To be added<br />
<br />
<br />
==uIP Ethernet Application==<br />
<br />
===DHCP Client===<br />
*Enable UDP in "uip-config.h"<br />
#define UIP_CONF_UDP 1<br />
*Make sure your uip buffer size is large enough (DHCP messages from some servers can be more than 500 bytes). In my setting, I use 1536 in "uip-config.h"<br />
#define UIP_CONF_BUFFER_SIZE 1536<br />
*Include the dhcpc.h header file in "uip-config.h"<br />
#include "dhcpc.h"<br />
*Change PT_WAIT_UNTIL(...) to PT_YIELD_UNTIL(...) in line 259 and 276 in "dhcpc.c" [This is a known bug in dhcpc.c]<br />
*In your main loop, initialize your MAC address and DHCP if UIP_FIXEDADDR is 0 in "uip-opt.h", for example:<br />
int main(void)<br />
{<br />
uip_ipaddr_t ipaddr;<br />
struct timer periodic_timer, arp_timer;<br />
struct uip_eth_addr mac = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06};<br />
<br />
timer_set(&periodic_timer, CLOCK_SECOND / 2);<br />
timer_set(&arp_timer, CLOCK_SECOND * 10);<br />
<br />
tapdev_init();<br />
uip_init();<br />
<br />
uip_setethaddr(mac);<br />
dhcpc_init(&mac, 6);<br />
<br />
while(1){<br />
//normal codes goes here<br />
}<br />
}<br />
*Implement dhcpc_configured(). This function will be called after DHCP client has obtained an IP address. Basically, you have to at least set your IP address, subnet mask and default gateway, for example,<br />
void dhcpc_configured(const struct dhcpc_state *s)<br />
{<br />
uip_sethostaddr(s->ipaddr);<br />
uip_setnetmask(s->netmask);<br />
uip_setdraddr(s->default_router);<br />
<br />
//you can print your ip addr to your console/lcd to see if you get a valid ip address<br />
}<br />
*An example of using DHCP Client in the dsPic33F development board can be found [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/common/app_http.c?root=freertos_posix&view=markup here].<br />
<br />
===Web Server===<br />
*Include the "webserver.h" header file in "uip-config.h"<br />
#include "webserver.h"<br />
*Modify httpd-fs.h<br />
**HTTPD_FS_STATISTICS set to 0<br />
*Create a website using HTML tags with/without Javascript<br />
*Modify httpd-fs.c<br />
**changed #include "httpd-fsdata.c" to #include <httpd-fsdata.c> <br />
*Generate httpd-fsdata.c for your website by executing '''perl makefsdata''' under your web root directory.<br />
====add-on====<br />
*The Web Server included in uIP 1.0 has been designed to load/reload the entire page (either html/shtml files) in response to a HTTP GET command, e.g.<br />
GET /index.html HTTP/1.1<br />
GET /abc.shtml HTTP/1.1<br />
*As a result, if the webpage is required to refresh the dynamic data periodically, the surfing experience will be degraded by the large transfer of datastream.<br />
*In consideration of the above issue, a solution is proposed here, so that the webserver can handle this kind of cgi HTTP-request<br />
GET /abc.shtml?val=500.0&button=Set HTTP/1.1<br />
*Modify httpd.c<br />
**added #include "httpd-hget.h" in line 63<br />
**added httpd_hget(s->filename) in line 224<br />
*Create httpd-hget.h<br />
**added to generate dynamic pages, e.g. /abc.shtml?button=Refresh<br />
#ifndef __HTTPD_HGET_H__<br />
#define __HTTPD_HGET_H__<br />
extern void httpd_hget(char *name);<br />
#endif<br />
*Create httpd-hget.c<br />
**an example is shown [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/dspic33/rackmount/04_uip/uip/httpd-hget.c?root=freertos_posix&view=markup here]<br />
<br />
==SNMP Agent==<br />
*Simple Network Management Protocol (SNMP) is a standard protocol to access variables to remote device via the Internet.<br />
*It belongs to the Application Layer, as in HTTP.<br />
*If a device is SNMP compatible, any SNMP compatible host system can monitor and control that device.<br />
<br />
===Components in a SNMP System===<br />
*Network Management Station (NMS)<br />
**This is a client, initiating SNMP communication.<br />
**This can be a PC with an NMS software (e.g. [http://nino.sourceforge.net/nino/index.html NINO]), polling data from the SNMP agents periodically.<br />
*SNMP Agents<br />
**These are servers, responding to one or multiple NMS requests.<br />
*Management Information Base (MIB)<br />
**A special collection of variables managed by the SNMP agents.<br />
**MIB has a tree-like structure.<br />
**An Object Identifier (OID) is given for each node.<br />
**Data are stored at the end-nodes.<br />
**Private variables may be constructed under the "enterprise" sub-tree.<br />
**The OID for "enterprise" can be obtained from [http://www.iana.org/cgi-bin/enterprise.pl Internet Assigned Number Authority (IANA)].<br />
<br />
===Abstract Syntax Notation===<br />
*Each MIB variable contains several attributes, such as data type, access type and object identifier.<br />
*Abstract Syntax Notation version 1 (ASN.1) is a language to define these attributes in SNMP.<br />
<br />
<br />
==Architecture==<br />
+---------------------------------------------+--------------------+-------+<br />
Applications | Ethernet Application | GUI Application | ... |<br />
+--------+------+------+----------+------+----+ | |<br />
Web Libraries | Web | DHCP | SNMP | DNS | SMTP |... | | |<br />
| Server | | | Resolver | | | | |<br />
+--------+------+------+----------+------+----+ | |<br />
Socket API | Linux-like Socket | | |<br />
+---------------------------------------------+ | |<br />
TCP/IP Stack | uip | | |<br />
+---------------------------------------------+ | |<br />
| Ethernet Controller | | |<br />
+--------------------------------------+------+--------------------+-------+<br />
POSIX API | POSIX System Calls | POSIX Threads |<br />
+--------------------------------------+-----------------------------------+<br />
| Drivers | Task Scheduler |<br />
+--------------------------------------+-----------------------------------+<br />
<br />
==Reference==<br />
===DM9000A===<br />
*[http://www.davicom.com.tw/eng/products/dm9000a.htm DM9000A Description]<br />
*[http://www.davicom.com.tw/big5/download/Data%20Sheet/DM9000A-DS-F01-101906.pdf DM9000A Datasheet]<br />
*[http://www.davicom.com.tw/big5/download/AC/dm9000a/DM9000A%20circuit_EMI_052306.pdf Application Circuit]<br />
*[http://www.davicom.com.tw/big5/download/LayoutGuide/DM9000A_9010-LG-V11_031706.pdf Layout Guidelines]<br />
*[http://www.davicom.com.tw/big5/download/ApplicationNote/DM9000A%20Application%20Notes%20Ver%201_20_101906.pdf Application Note]<br />
*[http://www.davicom.com.tw/eng/download/Driver/driver_9000.htm DM9000A Official Drivers]<br />
===dsPic33F Development Board===<br />
*[http://opencircuits.com/DsPIC30F_5011_Development_Board dsPic33F Development Board]<br />
===uIP===<br />
*[http://www.sics.se/~adam/uip/index.php/Main_Page uIP Description]<br />
*[http://www.sics.se/~adam/uip/index.php/Documentation uIP Documentation]<br />
*[http://www.sics.se/~adam/uip/index.php/Download Download]<br />
*[http://sourceforge.net/cvs/?group_id=186227 CVS Repository]<br />
===lwIP===<br />
*[http://savannah.nongnu.org/projects/lwip/ lwIP Description]<br />
*[http://www.nongnu.org/lwip/ Documentation]<br />
===HTML===<br />
*[http://www.w3schools.com/default.asp W3 Schools]: Learning how to write HTML and JavaScript<br />
*[http://www.nvu.com/index.php Nvu]: Open source HTML Editor<br />
===SNMP===<br />
*[http://www.snmplink.org SNMP Link]: Information on SNMP Agents<br />
*[http://pen.iana.org/pen/PenApplication.page IANA]: Applying a Private Enterprise Number</div>Yanhttp://www.opencircuits.com/index.php?title=Ethernet_Module&diff=16454Ethernet Module2008-09-29T07:39:37Z<p>Yan: /* ToDo List */ adding SSL</p>
<hr />
<div>==Introduction==<br />
*let a device have the following capabilities<br />
**can be controlled by a general browser in a desktop computer<br />
**access a server by itself to providing data, such as: device model no., serial no., any application data, or send out email for any events.<br />
*This project aims to develop an Ethernet Module, to be used in conjunction with a 8/16 bits embedded system such as the [http://opencircuits.com/DsPIC30F_5011_Development_Board dsPic33F development board].<br />
*[{{SERVER}}/Ethernet_Module#Architecture Architecture]<br />
<br />
==Bug List==<br />
*DHCP<br />
**dhcp client fault from buffalo router<br />
**occasionally cannot access webserver with dhcp<br />
<br />
*DHCP<br />
**dhcp client fault from main router<br />
**occasionally cannot access webserver with dhcp<br />
**possible cause: module tries to get IP configuration when switching on and off too frequently. This causes the router to enter into an unknown state. Even using the static mode with the same IP cannot get Internet access properly. When wait for some time and switch on the module again, the router may have been "reset", and the connection is ok again.<br />
<br />
<br />
==ToDo List==<br />
*32kB constant limitations<br />
**see if webserver can be stored in flash in file system<br />
*SNMP<br />
**porting snmp to uip<br />
**reference to lwip<br />
*SMTP<br />
**some router cannot used SMTP module<br />
**the router return its own IP as DNS resolver, and it does support only parsing direct IP function<br />
**desktop applications (e.g. outlook, thunderbird, webmail) do not use DNS resolver (UDP application) to connect to the mail server, but use TCP/IP to do the job<br />
*https by SSL<br />
**on chip SSL(more faster) OR software SSL(need to upgrade CPU power to process the calculation)<br />
**reference - http://www.networkworld.com/news/tech/2002/0729tech.html<br />
<br />
==Hardware==<br />
===Component List===<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
! Special Item !! Description !! Quantity<br />
|-valign="top"<br />
| [http://www.davicom.com.tw/big5/download/Data%20Sheet/DM9000A-DS-F01-101906.pdf DM9000AEP] || Ethernet Controller from [http://www.davicom.com.tw/eng/index.htm Davicom] || 1<br />
|-<br />
| [http://www.hanrun.com/hr/upfile/2_1_113.pdf HR911102A] || RJ45 Connector with Integrated Magnetics for 10/100 Base-TX || 1<br />
|-<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/21749F.pdf 93LC46B-I/SN] || 1K Serial EEPROM || 1 (Optional)<br />
|-<br />
| 25MHz Crystal || Crystal || 1<br />
|-<br />
| 22pF || For Crystal Use || 2<br />
|-<br />
| 220uF || For RXVDD25/TXVDD25 || 1<br />
|-<br />
| 49.9ohm || For RX+/RX-/TX+/TX- || 4<br />
|-<br />
| 6.8kohm || For BGRES/BGGND || 1<br />
|-<br />
| 510ohm || For LEDs|| 2<br />
|-<br />
|}<br />
<br />
===Circuit and PCB===<br />
in [http://chungyan5.no-ip.org/vc/?root=ethernet gEDA format]<br />
and its gEDA [http://www.opencircuits.com/PCB_Footprints#gEDA_Symbols_and_footprints sym and footprints]<br />
<br />
<br />
==Software Driver==<br />
*Download [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/dm9000a.c?root=freertos_posix&view=markup dm9000a.c]<br />
*Download [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/include/dm9000a.h?root=freertos_posix&view=markup dm9000a.h]<br />
*Base on [http://www.freertos.org/ FreeRTOS] and [http://opencircuits.com/DsPIC30F_5011_Development_Board dsPIC33 platform]<br />
*Using POSIX-like API:<br />
**'''int dmfe_open(int flags)''': initialize the Ethernet controller for 10MHz Half-Duplex<br />
**'''int dmfe_close()''': turn off the PHY layer<br />
**'''int dmfe_read(void)''': copy a packet to the default buffer<br />
**'''int dmfe_write(unsigned char device, unsigned char *buf, int count)''': copy count bytes of the data from buf and transmit<br />
**'''void dmfe_interrupt(void)''': process the transmit interrupt from DM9000A<br />
<br />
<br />
==TCP/IP Stack==<br />
*uIP and lwIP are light weight TCP/IP Stack designed for 8-bit/16-bit embedded systems.<br />
<br />
----<br />
<br />
===uIP===<br />
*Develped by Adam Dunkels of the Networked Embedded Systems group at the Swedish Institute of Computer Science.<br />
*[http://www.sics.se/~adam/uip/ uIP] is under the [http://www.sics.se/~adam/uip/index.php/License BSD-style license]<br />
====CVS Repository====<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
! Attribute !! Value<br />
|-valign="top"<br />
| Host || uip-stack.cvs.sourceforge.net<br />
|-<br />
| Repository Path || /cvsroot/uip-stack<br />
|-<br />
| Connection Type || pserver<br />
|-<br />
| User || anonymous<br />
|-<br />
|}<br />
*Changes made to CVS Repository (tag: HEAD v1.1)<br />
**'''uip.c'''<br />
***Comment out all DEBUG_PRINTF(...) in lines 1, 323, 910, 1015, 1070, 1863, 1868, 1869<br />
**'''uip.h'''<br />
***Change line 1070 to<br># define HTONS(n) (u16_t)(((((u16_t) (n)) << 8)&0xff00) | ((((u16_t) (n)) >> 8)&0x00ff))<br />
**'''psock.c'''<br />
***Change line 188 to<br>s->sendptr = (u8_t*) buf;<br />
***Change lines 276, 303 to<br>buf_setup(&psock->buf, (u8_t*)(psock->bufptr), psock->bufsize);<br />
***Change line 334 to<br>buf_setup(&psock->buf, (u8_t*)buffer, buffersize);<br />
<br />
====Porting====<br />
*Include the following files to use the uIP stack<br />
**timer.c<br />
**uip.c<br />
**uip_arp.c<br />
**psock.c<br />
*The following files have been created to port uIP 1.0 to dsPic33F development board using FreeRTOS<br />
*[http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/clock-arch.c?root=freertos_posix&view=markup clock-arch.c]: return the os tick counts since the system is turned on.<br />
*[http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/include/clock-arch.h?root=freertos_posix&view=markup clock-arch.h]: a constant specifying the number of os ticks in one second.<br />
*[http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/dspic33/rackmount/04_uip/include/uip-conf.h?root=freertos_posix&view=markup uip-config.h]: configuration for your application.<br />
<br />
----<br />
<br />
===lwIP===<br />
*[http://savannah.nongnu.org/projects/lwip/ lwIP] is a small independent implementation of uIP.<br />
*It is more powerful than uIP but requires more memory.<br />
*lwIP is under the [http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5 Modified BSD License]<br />
====CVS Repository====<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
! Attribute !! Value<br />
|-valign="top"<br />
| Host || cvs.savannah.nongnu.org<br />
|-<br />
| Repository Path || /sources/lwip<br />
|-<br />
| Connection Type || pserver<br />
|-<br />
| User || anonymous<br />
|-<br />
|}<br />
====Porting====<br />
*To be added<br />
<br />
<br />
==uIP Ethernet Application==<br />
<br />
===DHCP Client===<br />
*Enable UDP in "uip-config.h"<br />
#define UIP_CONF_UDP 1<br />
*Make sure your uip buffer size is large enough (DHCP messages from some servers can be more than 500 bytes). In my setting, I use 1536 in "uip-config.h"<br />
#define UIP_CONF_BUFFER_SIZE 1536<br />
*Include the dhcpc.h header file in "uip-config.h"<br />
#include "dhcpc.h"<br />
*Change PT_WAIT_UNTIL(...) to PT_YIELD_UNTIL(...) in line 259 and 276 in "dhcpc.c" [This is a known bug in dhcpc.c]<br />
*In your main loop, initialize your MAC address and DHCP if UIP_FIXEDADDR is 0 in "uip-opt.h", for example:<br />
int main(void)<br />
{<br />
uip_ipaddr_t ipaddr;<br />
struct timer periodic_timer, arp_timer;<br />
struct uip_eth_addr mac = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06};<br />
<br />
timer_set(&periodic_timer, CLOCK_SECOND / 2);<br />
timer_set(&arp_timer, CLOCK_SECOND * 10);<br />
<br />
tapdev_init();<br />
uip_init();<br />
<br />
uip_setethaddr(mac);<br />
dhcpc_init(&mac, 6);<br />
<br />
while(1){<br />
//normal codes goes here<br />
}<br />
}<br />
*Implement dhcpc_configured(). This function will be called after DHCP client has obtained an IP address. Basically, you have to at least set your IP address, subnet mask and default gateway, for example,<br />
void dhcpc_configured(const struct dhcpc_state *s)<br />
{<br />
uip_sethostaddr(s->ipaddr);<br />
uip_setnetmask(s->netmask);<br />
uip_setdraddr(s->default_router);<br />
<br />
//you can print your ip addr to your console/lcd to see if you get a valid ip address<br />
}<br />
*An example of using DHCP Client in the dsPic33F development board can be found [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/common/app_http.c?root=freertos_posix&view=markup here].<br />
<br />
===Web Server===<br />
*Include the "webserver.h" header file in "uip-config.h"<br />
#include "webserver.h"<br />
*Modify httpd-fs.h<br />
**HTTPD_FS_STATISTICS set to 0<br />
*Create a website using HTML tags with/without Javascript<br />
*Modify httpd-fs.c<br />
**changed #include "httpd-fsdata.c" to #include <httpd-fsdata.c> <br />
*Generate httpd-fsdata.c for your website by executing '''perl makefsdata''' under your web root directory.<br />
====add-on====<br />
*The Web Server included in uIP 1.0 has been designed to load/reload the entire page (either html/shtml files) in response to a HTTP GET command, e.g.<br />
GET /index.html HTTP/1.1<br />
GET /abc.shtml HTTP/1.1<br />
*As a result, if the webpage is required to refresh the dynamic data periodically, the surfing experience will be degraded by the large transfer of datastream.<br />
*In consideration of the above issue, a solution is proposed here, so that the webserver can handle this kind of cgi HTTP-request<br />
GET /abc.shtml?val=500.0&button=Set HTTP/1.1<br />
*Modify httpd.c<br />
**added #include "httpd-hget.h" in line 63<br />
**added httpd_hget(s->filename) in line 224<br />
*Create httpd-hget.h<br />
**added to generate dynamic pages, e.g. /abc.shtml?button=Refresh<br />
#ifndef __HTTPD_HGET_H__<br />
#define __HTTPD_HGET_H__<br />
extern void httpd_hget(char *name);<br />
#endif<br />
*Create httpd-hget.c<br />
**an example is shown [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/dspic33/rackmount/04_uip/uip/httpd-hget.c?root=freertos_posix&view=markup here]<br />
<br />
==SNMP Agent==<br />
*Simple Network Management Protocol (SNMP) is a standard protocol to access variables to remote device via the Internet.<br />
*It belongs to the Application Layer, as in HTTP.<br />
*If a device is SNMP compatible, any SNMP compatible host system can monitor and control that device.<br />
<br />
===Components in a SNMP System===<br />
*Network Management Station (NMS)<br />
**This is a client, initiating SNMP communication.<br />
**This can be a PC with an NMS software (e.g. [http://nino.sourceforge.net/nino/index.html NINO]), polling data from the SNMP agents periodically.<br />
*SNMP Agents<br />
**These are servers, responding to one or multiple NMS requests.<br />
*Management Information Base (MIB)<br />
**A special collection of variables managed by the SNMP agents.<br />
**MIB has a tree-like structure.<br />
**An Object Identifier (OID) is given for each node.<br />
**Data are stored at the end-nodes.<br />
**Private variables may be constructed under the "enterprise" sub-tree.<br />
**The OID for "enterprise" can be obtained from [http://www.iana.org/cgi-bin/enterprise.pl Internet Assigned Number Authority (IANA)].<br />
<br />
===Abstract Syntax Notation===<br />
*Each MIB variable contains several attributes, such as data type, access type and object identifier.<br />
*Abstract Syntax Notation version 1 (ASN.1) is a language to define these attributes in SNMP.<br />
<br />
<br />
==Architecture==<br />
+---------------------------------------------+--------------------+-------+<br />
Applications | Ethernet Application | GUI Application | ... |<br />
+--------+------+------+----------+------+----+ | |<br />
Web Libraries | Web | DHCP | SNMP | DNS | SMTP |... | | |<br />
| Server | | | Resolver | | | | |<br />
+--------+------+------+----------+------+----+ | |<br />
Socket API | Linux-like Socket | | |<br />
+---------------------------------------------+ | |<br />
TCP/IP Stack | uip | | |<br />
+---------------------------------------------+ | |<br />
| Ethernet Controller | | |<br />
+--------------------------------------+------+--------------------+-------+<br />
POSIX API | POSIX System Calls | POSIX Threads |<br />
+--------------------------------------+-----------------------------------+<br />
| Drivers | Task Scheduler |<br />
+--------------------------------------+-----------------------------------+<br />
<br />
==Reference==<br />
===DM9000A===<br />
*[http://www.davicom.com.tw/eng/products/dm9000a.htm DM9000A Description]<br />
*[http://www.davicom.com.tw/big5/download/Data%20Sheet/DM9000A-DS-F01-101906.pdf DM9000A Datasheet]<br />
*[http://www.davicom.com.tw/big5/download/AC/dm9000a/DM9000A%20circuit_EMI_052306.pdf Application Circuit]<br />
*[http://www.davicom.com.tw/big5/download/LayoutGuide/DM9000A_9010-LG-V11_031706.pdf Layout Guidelines]<br />
*[http://www.davicom.com.tw/big5/download/ApplicationNote/DM9000A%20Application%20Notes%20Ver%201_20_101906.pdf Application Note]<br />
*[http://www.davicom.com.tw/eng/download/Driver/driver_9000.htm DM9000A Official Drivers]<br />
===dsPic33F Development Board===<br />
*[http://opencircuits.com/DsPIC30F_5011_Development_Board dsPic33F Development Board]<br />
===uIP===<br />
*[http://www.sics.se/~adam/uip/index.php/Main_Page uIP Description]<br />
*[http://www.sics.se/~adam/uip/index.php/Documentation uIP Documentation]<br />
*[http://www.sics.se/~adam/uip/index.php/Download Download]<br />
*[http://sourceforge.net/cvs/?group_id=186227 CVS Repository]<br />
===lwIP===<br />
*[http://savannah.nongnu.org/projects/lwip/ lwIP Description]<br />
*[http://www.nongnu.org/lwip/ Documentation]<br />
===HTML===<br />
*[http://www.w3schools.com/default.asp W3 Schools]: Learning how to write HTML and JavaScript<br />
*[http://www.nvu.com/index.php Nvu]: Open source HTML Editor<br />
===SNMP===<br />
*[http://www.snmplink.org SNMP Link]: Information on SNMP Agents<br />
*[http://pen.iana.org/pen/PenApplication.page IANA]: Applying a Private Enterprise Number</div>Yanhttp://www.opencircuits.com/index.php?title=GPIB&diff=16453GPIB2008-09-29T07:26:21Z<p>Yan: init. this doc.</p>
<hr />
<div>==Introduction==<br />
*http://www.ni.com/gpib/what_is.htm / http://en.wikipedia.org/wiki/IEEE-488<br />
*it is one of a communication standard of most equipments<br />
*A interface(in both hw & sw) to any platforms, such as dspic33 board, bf1 board ...<br />
<br />
==interface==<br />
<br />
===I2C protocol===<br />
*apply as one to many(can be different kind of devices)<br />
*different platforms<br />
**for dspic, sw driver implement in freertos following posix arch.<br />
**for bf1 pf, sw driver implment in uclinux following posix arch.</div>Yanhttp://www.opencircuits.com/index.php?title=Projects&diff=16451Projects2008-09-29T06:29:04Z<p>Yan: adding gpib</p>
<hr />
<div>=== Open Circuits ===<br />
<br />
These should be projects or links to projects that are open, at a minimum in the sense that there is enough information so that others can reproduce the project. Lets stay away from sites that are just show cases without the details.<br />
<br />
<br />
=== Open Source Disability Gadgets ===<br />
<br />
* "Gear and software for people with disabilities is usually ... hard or impossible to repair it, or get anyone to repair it. We need to hack the model for accessibility tools! With a culture of open source designs, Instructables, wikis, and blogs" -- [http://panelpicker.sxsw.com/ideas/view/1745 Open Source Disability Gadgets: DIY for PWD]<br />
<br />
=== µWatch ===<br />
<br />
* [http://www.calcwatch.com/ µWatch]: World's First D-I-Y Scientific Calculator Watch<br />
<br />
=== Open Source Circuits Magazine ===<br />
[http://www.anykits.com/ Anykits magazine]<br />
- Anykits publishes an open source magazine with quite a few, application oriented circuits. It contains schematics, parts list and PCB illustrations.<br />
The best part is that its formated for print and available as regular PDF.<br />
<br />
=== Open OBDII ===<br />
[http://www.sterntech.com/obdii.php Link to source and schematics]<br />
Open source hardware and software implementing OBDII tester for cars. <br />
Two versions one using a PIC microcontroller and one using an AVR microcontroller.<br />
<br />
=== [[vehicle]]s: manned and unmanned ===<br />
Lots of [[vehicle | vehicle-related projects]] -- for motorcycles, automobiles, and unmanned aerial vehicles (UAVs).<br />
<br />
=== Phone line relay controller with PIC16F84A - single relay ===<br />
* [http://www.elektronika.ba/projekti/?akc=daj_projekt&idprojekt=10] controll one relay over phone-line. Uses PIC16F84A and MT8870.<br />
<br />
=== Phone line relay controller with PIC16F876A - 6 relays! ===<br />
* [http://www.elektronika.ba/projekti/?akc=daj_projekt&idprojekt=11] controll up to 6 relays over phone-line. Uses PIC16F876A and MT8870.<br />
<br />
===Homemade MIDI turntable===<br />
Cheap and simple homemade MIDI turntable with GPL2 license. Using a ATmega, a HDNS-2000 optical mouse encoder, GCC-AVR, AVR-Libc and FreeRTOS. [http://casainho.net/tiki-index.php?page=Homemade+midi+turntable Homepage of Homemade MIDI turntable].<br />
<br />
=== Motherboards that Run Linux ===<br />
<br />
==== [[ARMUS Embedded Linux Board]] ====<br />
An ARM920T board running Linux at 200 Mips with sound, Ethernet, CAN, 48+ bidirectionnal IOs and 4 DSPs for motor control (DC, Servos, etc...). Built as a student proof robotics design platform.<br />
<br />
==== [http://balloonboard.org Balloon Xscale ARM+FPGA dev board] ====<br />
The Balloon project has produced Balloon3, a high-performance ARM board designed for use by OEMs and Higher education. Spec is PXA270 (583Mhz), FPGA or CPLD, 1GB flash, 784MB RAM, USB (master, slave, OTG), CF slot, expansion bus, 16-bit bus, I2C, LCD, serial, audio. Very low power in CPLD confiuguration. Small, light. Various add-on boards: VGA LCD driver, robot motor driver+A/D, digital IO. Released under the Balloon Open Hardware license, which allows anyone to manufacture and for people to make derivatives. The expansion bus allows balloon to be used as the computing component for various special-purpose devices.<br />
<br />
==== [[Linuxstamp]] ====<br />
The linuxstamp is an open source processor module. It is designed to be a very simple board capable of running linux. It is based on the Atmel AT91RM9200 processor (An ARM9 processor with a MMU).<br />
<br />
==== [[Linuxstamp Mboard 1]] ====<br />
This is the first mother board for the linuxstamp. It is still in the planning stages (no pcbs).<br />
<br />
==== [http://www.linuxdevices.com/links/LK9764937601.html LART -- an open license StrongARM based tiny SBC] ====<br />
<br />
"All CAD files required for building LART are available under the closest we could get to an Open/Free Hardware License."<br />
(Has this information [http://www-it.et.tudelft.nl/~inald/html/research.htm#MMC gone offline?])<br />
<br />
==== Other Boards that Run Linux ====<br />
<br />
* Is it possible to [http://groups.google.com/group/comp.arch.embedded/browse_thread/thread/be085ff0772cde21/8331dee5db8eb083#8331dee5db8eb083 Linux on a "soft CPU"] inside a FPGA?<br />
<br />
* [http://www.linuxhosts.org/article.cfm/id/158855 The ARM9 AT91SAM9261 is capable of running Linux].<br />
* [http://www.linuxdevices.com/articles/AT8498487406.html "teeny weeny Linux single board computers"]<br />
<br />
=== [[Programmable Chip EEG]] ===<br />
The Programmable Chip EEG is a Multi-channel electroencephalograph that could be a brain-computer interface.<br />
See the [http://openeeg.sourceforge.net/doc/ OpenEEG Project]<br />
<br />
=== [[Open Mobile Gadgets]] -- open source, open hardware, mobile phone ===<br />
An open source, open hardware mobile phone in its preliminary development.<br />
<br />
=== [[Music Player]]s including MP3 players ===<br />
<br />
* [[TRAXMOD]] Open source MOD music player for dsPIC/ARM microcontrollers.<br />
<br />
* [[Music Player]] Mostly off site.<br />
<br />
=== [[PG31 GPS RS232 Dev Board]] ===<br />
A simple RS232 example project that takes 3.3V TTL serial and outputs to a super-common RS232 connection. Insto-NMEA!<br />
<br />
=== [[RS232 Dev Board]] ===<br />
A simple RS232 example project that takes all the power it needs from the serial port. Use it to power your microcontroller and communicate between serial port and microcontroller. Takes advantage of the fact that pc serial ports will accept 0-5V rather than the RS232 standard of around negative 10V to positive 10V. Very convenient - no external power required! Note that you may use either a 5.1V Zener or a 5V regulator.<br />
<br />
=== [[RS232 RS485 USB Converter Board]] ===<br />
Aim to build a general Converter between different Interfaces.<br />
<br />
=== [[PG31 GPS USB Dev Board]] ===<br />
A great example project using the CP2102 USB to TTL UART IC as well as some basic battery holder info.<br />
<br />
=== [[Chalk Roach|Number Six]] ===<br />
"#6" (the son of Chalk Roach)<br />
is a ultra simple microcontroller development board for Atmel ATmega32 = 16MHz, 2KB SRAM, 16KB Flash<br />
<br />
=== LED and POV displays ===<br />
<br />
Led displays range from a battery and an LED which light up ( cool!, add a magnet and you have an led throwie ) to microcontroller led projects, either Smart Led ( Led with a microcontroller so that it blinks, reacts to the environment, or shifts color ) or Led Arrays ( or led matrix ) that do simple graphics and or play games, or POV devices where what you see depends upon you persistance of vision ( which can include some led arrays ). You can probably dig up more using these terms in google.<br />
<br />
==== Our Own Projects ====<br />
<br />
* [[24" Wall Clock]] A really big wall clock. Why? Well, cause it might look cool? Probably not. But we do use GPS to get the time! Groovy.<br />
* [[POV display]] that spins around, giving the illusion of a large display. ([[User:DavidCary|DavidCary]])<br />
* [[PointLess LED Array]] A 8 by 8 array displays something using POV ([[russ_hensel]])<br />
* [[PIC Links]] and search on POV and/or LED<br />
<br />
==== Off Site ====<br />
<br />
* [http://code.google.com/p/bicycleledpov/ Bicycle LED POV] is an electronic LED bar to attach on bicycle wheels. When riding the bicycle, the LED bar will draw with light, text messages and image animations. Free/Open hardware, firmware and software.<br />
* [http://www.makezine.com/blog/archive/2007/03/luscious_electric_delight.html "luscious electric delight"]: source and schematics for a large graphical LED panel. Uses 12 MAX6953 LED drivers; each MAX6953 drives four 5x7 led matrices. The PC generates arbitrary bitmap, sends it out the serial port to a PIC, which translates it to I2C bus connected to all the MAX6953 LED drivers, which update the image at a continuous frame rate of 30fps.<br />
* [https://oldwiki.blinkenarea.org/bin/view/Blinkenarea/BlinkenProjects BlinkenProjects]: projects with lots of LEDs[http://www.kiu.weite-welt.com/de.schoar.blog/?p=206], including a 3D LED array. Wiki: http://wiki.blinkenarea.org/<br />
* [http://www.ianpaterson.org/projects/spokepov20050704/index.htm Ian’s Spoke POV] Review it.<br />
* [http://www.electric-clothing.com/superpov.html Project: Super POV] Review it.<br />
* [http://www.ladyada.net/make/spokepov/index.html SpokePOV Persistence of Vision for your Bike] Very nice, kit available.<br />
* [http://www.attiny.com/dotmatrix.htm On this page you will find a scrolling LED sign based on the ATtiny2313 AVR microcontroller] Row Column approach with a shift register]<br />
* [http://blog.makezine.com/archive/2007/02/flashing_led_br.html Flashing LED Bra]<br />
* [http://www.evilmadscientist.com/article.php/peggy "Peggy," A Light Emitting Pegboard Display]<br />
* Christmass trees are now led based so: [http://computerchristmas.com/ The #1 Site for Controlling Christmas Lights with a Computer]<br />
* [http://members.misty.com/don//ledx.html Don Klipstein's LED Main Page] Lots of good info.<br />
* [http://www.instructables.com/id/Synchronizing-Fireflies/ Synchronizing Fireflies] ATtiny super smart swarm of LEDs.<br />
* [http://www.u-disp.com/ U-Disp - An Open Sourced USB display]<br />
* [http://crushingabyss.com/sunrise_alarmclock/index.html Sunrise LED Alarm Clock] ATMega8515 controlling two color-mixed high-power LED channels with PWM. Also contains a RTC circuit and a serial port. Full source including PC Windows serial port communication code.<br />
<br />
=== [http://www.raccoonrezcats.com/rfdisplay.html RFDISPLAY - A Scrolling Display with RF connection to a PC ] ===<br />
<br />
POV scrolling display with an RF connection to a mini-itx computer and weatherstation. Project is built out of 384 discrete red LEDs. Display shows time and date, sunrise/sunset time and outdoor/indoor weather. <br />
<br />
Schematics, Board Layouts, and MPLAB C18 firmware source code is provided.<br />
<br />
=== [[Cellular Rotary Phone]] ===<br />
An indepth breakdown of the Port-O-Rotary. Some clues to help you avoid audio problems with the GM862.<br />
<br />
=== [[Das Brewmeister!]] and [[Fermenter Controller]] ===<br />
* [[Das Brewmeister!]] : An attempt to wirelessly monitor temperatures of fermentation vessels<br />
* [[Fermenter Controller]] : A web available fermenter vessel controller. Uses PICs, [[I2C]], Rs232 and python.<br />
<br />
=== [[Home controller]] ===<br />
Program your appliances to operate automatically in conjunction with your weekly and daily schedule, manually turn them on/off from your PC or use the controller as a process ON/OFF controller to regulate some kind of physical variable to the desired value.<br />
<br />
=== [[Interactive Lock Box]] ===<br />
An interesting project using an accelerometer and capacitive touch ICs.<br />
<br />
=== [[Motor driver]] (H-bridge) ===<br />
<br />
=== [[atomic microscope]] ===<br />
An atomic-resolution microscope.<br />
* STM (scanning tunnelling microscope)<br />
* AFM (atomic force microscope)<br />
<br />
=== [[BlueICE]] ===<br />
A bluetooth JTAG ICE debugger for AVR's!!!<br />
<br />
=== Sort-of-Networked [[RFID Reader]] ===<br />
A 125Khz RFID Reader with a simple ring network - to allow connection of multiple units to the same control computer.<br />
<br />
=== Battery charger ===<br />
<br />
See [http://elecdesign.com/Article/ArticleID/1823/1823.html "Build A Smart Battery Charger Using A Single-Transistor Circuit"] by Ejaz ur Rehman.<br />
But be sure to read the "Reader Comments" at the end.<br />
The suggestion to add a zener diode is a good idea.<br />
<br />
=== the Open Graphics Project ===<br />
<br />
[http://linux.wordpress.com/2006/07/19/introducing-the-open-graphics-project/ the Open Graphics Project]<br />
a project started by chip-designer Timothy Miller.<br />
His goal, along with the rest of the project, known as the “Open Graphics Foundation” is to make a 3D accelerated video card which is fully documented, free-licensed, and open source.<br />
See [http://wiki.duskglow.com/tiki-index.php?page=Open-Graphics the Open Graphics wiki].<br />
<br />
=== [[Amiga floppy project]] ===<br />
<br />
The Amiga floppy project:<br />
designing, building, and programming an adapter to allow PCs to read from Amiga floppies.<br />
"This is really designed to be a community project(hence the blog with progress reports)."<br />
<br />
This project is the building of an external USB amiga floppy drive controller. It sits between the USB port on a Windows PC, and a regular PC floppy drive. It will allow the PC to create .ADF images from an amiga floppy disk. This device is based on a Parallax SX28 microcontroller, uses Ramtron FRAM memory for temporary track storage, and uses another Parallax component for the USB interface.<br />
<br />
See http://www.techtravels.org/amiga/amigablog for the latest in the blow by blow attempts to get this thing off the ground!!<br />
<br />
=== Irsensor-a ===<br />
<br />
Infrared Proximity Sensor Alfa<br />
[http://www.kedo.com.mx/modules/content/index.php?id=3 Infrared Proximity Sensor Alfa in www.kedo.com.mx]<br />
<br />
The Infrared Proximity Sensor Alfa is a sensor to detect objects that can reflect infrared light. It has the following characteristics.<br />
* Designed to detect objects that are close and can reflect infrared lights.<br />
* It has a Infrared Transmitter to eliminate the dependency of solar lighting. So It can be used in the night.<br />
* It has a Infrared Receiver that detects the closest object that reflects the infrared lights.<br />
* It has an incorporated voltage regulator<br />
* The output is a constant 5V when it is active and 0V when no detection.<br />
* You can change the proximity threshold with a potentiometer.<br />
<br />
== [[DsPIC30F 5011 Development Board]] ==<br />
A development board using Microchip dsPIC30F5011, a 5V based 16-bit microcontroller with DSP functions, EEPROM, ADC, PWM and communciation ports of UARTs, I2C, SPI etc. Contains concise information on:<br />
#Development environments (IDE)<br />
#External programming methods (ICSP Programming using ICD2 Programmer)<br />
#Bootloader implementation (RTSP)<br />
#Software development tips based on POSIX concepts<br />
#Basic conversion tips to target board using Microchip dsPIC33FJ128GP306, a pin-to-pin compatible 3.3V microcontroller<br />
<br />
== [[Ethernet Module]] ==<br />
<br />
*This project aims to develop an Ethernet Module, to be used in conjunction with a 8/16 bits embedded system such as the [http://www.opencircuits.com/Projects#dsPIC30F_5011_Development_Board dsPic33F development board].<br />
*The entire Ethernet Module consists of:<br />
#Hardware: a LAN card based on Davicom DM9000A chip<br />
#Software: a TCP/IP stack based on uIP 1.0 or lwIP<br />
<br />
== [[Modulation Plugin]] ==<br />
<br />
*This project aims to develop an Modulation Plugin Module, to be used in conjunction with a 8/16 bits embedded system such as the [http://www.opencircuits.com/Projects#dsPIC30F_5011_Development_Board dsPic33F development board].<br />
<br />
== Scavenge ==<br />
<br />
Some people derive an inordinate amount of pleasure from building semi-useful objects from zero-cost junk.<br />
<br />
In the electronics field, most of the stuff built from scavenged components falls into 2 categories:<br />
* ham radio transmitters and receivers -- built from a few transistors, caps, resistors, and wire<br />
* BEAM robotics -- built from the above plus motors, solar cells, ...<br />
<br />
According to http://coprolite.com/art12.html ,<br />
"I'd love to hear about where you found your 8048. Take a picture of the host that you remove it from (CD player, truck, refridgerator, whatever) and I'll put your picture on a page that chronicles our adventures sifting through the rubble."<br />
<br />
Also see [[Free_From_Salvage]]<br />
<br />
=== openEyes ===<br />
openEyes is an open-source open-hardware toolkit for low-cost real-time eye tracking.<br />
See [http://hcvl.hci.iastate.edu/cgi-bin/openEyes.cgi the OpenEyes hardware and software] and [http://hcvl.hci.iastate.edu/cgi-bin/openEyeswiki/index.cgi the openEyes wiki].<br />
<br />
=== RepRap ===<br />
RepRap is an open source project to create a 3d printer or fabber machine. There is tons of information available on [http://www.reprap.org its website]. The current iteration is a 3 axis cartesian robot with 2 extruder heads: a Thermoplastic head that extrudes plastics like HDPE, ABS, and CAPA, and a support material head that extrudes a water soluble material to support the build process.<br />
<br />
The [http://burningsmell.org/biollante/ Biollante project] is a kind of RepRap that uses a 6 axis Stewart platform.<br />
Can devices from a [http://kmoddl.library.cornell.edu/ mechanical model library] be fabbed with RapRap?<br />
The article [http://ccsl.mae.cornell.edu/papers/Nature05_Zykov.pdf "Self-reproducing machines"] goes even further than just 6 identical parts -- it suggests that "self-reproducing machines composed of many identical microscale modules" may be a better design than the original RepRap design where just about every part is unique.<br />
<br />
"This is the meta-problem of engineering: Design a machine that can design other machines." -- Hod Lipson[http://www.mae.cornell.edu/lipson/]<br />
<br />
=== TwentyDollarWikiDevice ===<br />
<br />
Challenge: Build a Wiki Device with a parts cost of no more than twenty dollars which is usable as a portable wiki. Include feature to make it compatible with a desktop or laptop computer's PersonalWiki, with a connector allowing this use.<br />
--<br />
http://c2.com/cgi/wiki?TwentyDollarWikiDevice<br />
<br />
"hardware portable wiki for taking notes with an auto-merging functionality when you are very close to Internet or your computer."<br />
--<br />
http://communitywiki.org/AlexandreDulaunoy<br />
<br />
=== [[breakout boards]] ===<br />
These are three boards that I designed for a specific project and found them very useful. Each of these boards uses the phoenix contact plugable terminal blocks. The 50-pin breakout board is for a 50-pin ribbon cable. The LEM breakout board is for LEM AC/DC current sensor. The power supply breakout board is for a +5v +/-15v power supply.<br />
<br />
=== Free Telephony Project ===<br />
<br />
[http://www.rowetel.com/ucasterisk Free Telephony Project]<br />
<br />
* Embedded Asterisk IP-PBX hardware and software<br />
<br />
* Low cost, completely open IP-PBX hardware including FXS/FXO analog and E1/T1 interfaces, and DSP motherboard hardware. Target price of $100 for a 4 port IP-PBX.<br />
<br />
=== Eyes for Open Robot ===<br />
<br />
* [http://www.sparkfun.com/commerce/product_info.php?products_id=637 $20 CMOS Camera Module - 640x480] has a [http://forum.sparkfun.com/viewtopic.php?t=2442 "Get-that-camera-working competition" discussion forum] and [http://www.makezine.com/blog/archive/2007/01/hack_this_cmos.html now been adequately documented] ... http://elinux.org/wiki/SparkfunCamera ... [http://forum.sparkfun.com/viewtopic.php?t=2442&postdays=0&postorder=asc&start=135 by David Carne].<br />
<br />
* ... perhaps simpler to use an off-the-shelf webcam that plugs directly into a laptop ... [http://www.linux.com/howtos/Webcam-HOWTO/hardware.shtml Enabling Support for Your (Webcam) Hardware in Linux] ... [http://www.saillard.org/linux/pwc/ Philips USB Webcam Driver for Linux] ... [http://qce-ga.sourceforge.net/ QuickCam] ...<br />
<br />
''Is there a simple way for my Java application to fetch the latest camera image in an Array of pixel values?''<br />
<br />
=== robot ===<br />
<br />
* open architecture humanoid robotics platform --[http://www.is.aist.go.jp/humanoid/openhrp/English/indexE.html OpenHRP]<br />
<br />
=== RCAP: R/C Auto Pilot: Remote Control Auto Pilot ===<br />
<br />
"The RCAP2 is a Remote Control AutoPilot] for model airplanes, cars and boats. The autopilot function can be switched off or on during flight with the flick of a switch." Uses PIC16F876A to:<br />
* read (servo) commands from the RC server<br />
* read (RS-232) GPS location from a NMEA capable GPS (with programmable goto/waypoints functions)<br />
* drive (servo) commands to the rudder.<br />
<br />
[http://en.wikibooks.org/wiki/RCAP RCAP Documentation at Wikibooks ],<br />
and [http://rcpilot.sourceforge.net/modules/rcap/index.php RCAP PCB layout at Sourceforge ].<br />
<br />
== [http://www.remember.ro/scripts/wiegand.php Wiegand reader simple controller] ==<br />
<br />
The PICmicro 16F628 decodes [http://en.wikipedia.org/wiki/Wiegand_protocol Wiegand protocol] coming from card reader.<br />
If the card matches one of the 40 cards in EEPROM, it turns on the light (opens the door).<br />
Schematic and source code published under GNU terms.<br />
<br />
== [http://www.rcrowley.com/ComClone/default.htm ComClone2 Intercom] ==<br />
<br />
ComClone2 is a DIY clone of the industry-standard "party line" production intercom system as first introduced by Clearcom and now sourced by many other vendors. This intercom system is widely used in both live show(theatrical, music, etc.) and video production. Website provides complete construction information including PC board, etc.<br />
<br />
== Minimig ==<br />
<br />
[[Minimig|Amiga 500 implemented]] with Xilinx FPGA + Freescale mc68000<br />
<br />
== [http://www.raccoonrezcats.com/soundcard.html USB Audio Streamer : A Homebrew USB Soundcard ] ==<br />
<br />
This project is a homebrew 12bit 24KHz homebrew USB soundcard based on a pic 18f2550 and a few Microchip analog parts.<br />
The project is based on the Microchip USB framework, but the core audio processing is written from scratch.<br />
The card is a duel Audio 1.0 + generic interface composite device with the generic interface being handled by WinUSB. <br />
The schematic, card firmware, and host C++ software is provided.<br />
<br />
== [http://www.raccoonrezcats.com/rfmodem.html PINGPONG-CDC : A Homebrew USB FHSS RF Modem ] ==<br />
<br />
The PINGPONG-CDC project is a homebrew USB frequency hopping spread spectrum RF modem ([[FHSS]]). The modem is based on the Microchip 18F2550 and the Semtec XE1205 RF module. The module does not include a MAC or protocol layer. That is what this project implements. The project demonstrates how to write a FHSS MAC layer and use USB to interface it with a PC through CDC and WinUSB.<br />
Since the protocol is not hard-wired, it is easy to change the software to experiment with different protocols.<br />
A utility for pairing and configuring modems is included. The schematic, firmware, and host C++ software is provided.<br />
<br />
== [http://www.raccoonrezcats.com/rfethernet.html XE1205-RNDIS : FCC Legal Frequency Hopping Spread Spectrum USB Wireless Ethernet ] ==<br />
<br />
This is the PINGPONG-CDC project that emulated ethernet through the RNDIS driver in Windows rather then a serial cable replacement. Full source code is provided.<br />
<br />
== An acceptable third generation PostScript printer ==<br />
<br />
"Ask the Guru: A Third-Generation Printer"<br />
article by Don Lancaster 1990<br />
http://www.tinaja.com/glib/guru60.pdf<br />
lists specifications for<br />
"An acceptable third generation PostScript printer."<br />
Would this be a good "open hardware" project ?<br />
<br />
<br />
== the [[Kestrel]] ==<br />
<br />
[http://archives.seul.org/geda/user/Aug-2004/msg00170.html "About the Kestrel"] by Samuel A. Falvo II 2004<br />
<br />
''(quote)''<br />
<br />
The Kestrel's intended purpose is to be a rational, grass-roots computer <br />
design employing half-way modern technology, where (quite unlike the PC) *EVERYTHING* is documented openly.<br />
BUT, not adopting every possible <br />
technology under the sun just because it exists. ... you'd get the circuit schematics, register-level <br />
programming information, timing diagrams, and descriptions of the <br />
ROM-resident OS interfaces ...<br />
<br />
The over-arching goals of the project remain the same:<br />
<br />
* An open, completely documented architecture, able to be described in a SINGLE BOOK. ...<br />
<br />
* Fan-less design, which means, low power, even at the expense of computation speed. ... I'm not aiming for the lowEST power -- but fanless design is critical.<br />
<br />
...<br />
<br />
* Instant on, (nearly) instant off. ... On the Amiga, you just waited 5 seconds, without touching anything, (that's it) for the disk caches to sync with the volumes, and then you flicked the power switch. End of discussion. Not so with Windows or Linux. Anyway, boot-up is way, way more expensive. It has to check RAM every freaking time ..., it probes the buses and takes its damn sweet time doing it, etc. AmigaOS did all this in a fraction of a second. Heck, even just spending 5 seconds is sufficient for me. But remember that this is added on to the start-up time of the OS you're loading too! The goal: instant on, instant off. Trust me -- it really DOES make a difference!<br />
<br />
...<br />
<br />
* Lightning fast I/O auto-detection. If the Amiga can do it with 8MHz processor technology, so can we with 66MHz. I simply cannot emphasize this enough.<br />
<br />
* Relatively easy to build. Since this is now an advanced kit idea, this isn't nearly as weighted as it used to be. Nonetheless, it is a goal to strive for.<br />
<br />
* Minimum cost. ...<br />
<br />
...<br />
<br />
The whole purpose is to have FUN with this computer -- to have fun <br />
building it, to have fun using it, to have fun expanding it. Part of <br />
this fun factor is being able to hack the hardware as much as you can <br />
hack the software.<br />
Commodore's IEC bus, HP's HP-IL, and Amiga's Zorro <br />
bus are all inspirations here.<br />
...<br />
it wasn't hard to build a Zorro <br />
card that fully interoperated with the system, you didn't need to be <br />
registered with anyone but Commodore (and they gave away mfr IDs for <br />
FREE), and full hardware interface details were available in the Amiga <br />
HRM for a cost of $29.99 US. It was bliss.<br />
<br />
* Everything is LGPLed. So if you DID want to include PCI slots or whatever, please feel free!! Just because it's not my personal priority with the system doesn't mean it's not someone else's. This is the beauty of open source and, indeed, [[open hardware]].<br />
<br />
...<br />
<br />
* Support for new business opportunities. ... This ties into the prime goal of this whole thing, which is,<br />
<br />
* The creation of a vibrant and healthy user and developer community, capable of supporting itself on both software AND hardware fronts.<br />
<br />
...<br />
<br />
''(end quote)''<br />
<br />
A more up-to-date description of<br />
[http://falvotech.com/content/kestrel/ The Kestrel Project].<br />
(several other pages on the Kestrel project nearby).<br />
<br />
== [[astronomy]] ==<br />
A variety of "open" tools for optical and radio astronomy.<br />
<br />
== flash downloaders ==<br />
Many people have published open-hardware schematics for downloading programs into the flash of various microcontrollers. [http://m8cutils.sourceforge.net/ m8cprogs for Cypress PSoC], [http://techref.massmind.org/techref/devprogs.htm various flash downloaders for Microchip PIC], etc.<br />
<br />
== [[WikiNode]] ==<br />
The WikiNode project tries to link every wiki in the world together.<br />
Our "[[WikiNode]]" links to closely-related wiki (and their WikiNode links back).<br />
<br />
If you want to talk about something that is not quite on-topic here at Open Circuits<br />
(say, "desktop PC case modding", or "embedded Linux programming"), our WikiNode helps you find another wiki where people love to talk about that exact topic.<br />
The corresponding WikiNode on each of those wiki helps people who want to talk about "open hardware" to discover this wiki.<br />
<br />
== arm7-oled-clock ==<br />
<br />
arm7-oled-clock is a clock hardware/software project for a clock with a graphic organic led display running on an atmel arm7 microcontroller.<br />
<br />
Here is the [http://code.google.com/p/arm7-oled-clock/ arm7-oled-clock's project page on google code].<br />
<br />
== Sun SPOTs ==<br />
<br />
[http://www.sun.com/ Sun Microsystems] has open sourced both hardware and software for the [http://research.sun.com/ Sun Microsystem Laboratories] Sun SPOT (Small Programmable Object Technology) Wireless Sensor Network. <br />
<br />
This Java-based system is an ARM920T 180MHz processor, 4Mbyte Flash, 512Kbyte pSRAM and 802.15.4 radio transceiver (TI CC2420). See the [http://www.sunspotworld.com/ Sun SPOT World] website for more information. We also have an active [https://www.sunspotworld.com/forums/ forum].<br />
<br />
The hardware designs can be downloaded from [https://spots-hardware.dev.java.net/ https://spots-hardware.dev.java.net]. The content available for download (subversion) are the schematics (pdf, Altium), bill of materials (Excel), assembly drawings (pdf), fabrication drawings (pdf), PC design files (Altium) and gerber files (RS274X) for these boards.<br />
<br />
The boards we have posted are:<br />
* eDemo: Demonstration add-on board for the Sun SPOT. <br />
* eFlash: MiniSD card reader/writer add on board for Sun SPOT <br />
* eProto: Prototype board with simple interface to Sun SPOT <br />
* eProtomega: eSPOT Prototyping board with Atmega88 processor <br />
* eSerial: RS232 Serial interface board for the Sun SPOT <br />
* eUSB-Host: USB host interface to Sun SPOT <br />
* eDaq: Industrial strength ADC board<br />
* eBones: Basic interface board application note<br />
* eSPOT: Main Sun SPOT board<br />
<br />
Our wiki for the hardware is [http://wiki.java.net/bin/view/Mobileandembedded/SpotHardware http://wiki.java.net/bin/view/Mobileandembedded/SpotHardware].<br />
<br />
SPOTs run Squawk, an open source Java virtual machine (VM). The download (and more information) for Squawk is [https://squawk.dev.java.net/ https://squawk.dev.java.net/]. The SPOT specific libraries can be downloaded from [https://spots-libraries.dev.java.net/ https://spots-libraries.dev.java.net/] along with community applications [https://spots-applications.dev.java.net/ https://spots-applications.dev.java.net/]<br />
<br />
<br />
== [[GPIB]] ==<br />
<br />
<br />
== Other Lists of Semi-Open Projects ==<br />
<br />
* UHF FM BUG with ButtonCell battery ( http://www.elektronika.ba/el.sheme/?akc=daj_shemu&idshema=490 ) "This bug is 100% made from an old Nokia GSM phone! It operates at 434 MHz and reception can be achieved on a modified TV tuner or 70cm band HAM radio."<br />
* [http://massmind.org/techref/microchip/alternatives.htm microcontroller alternatives] lists a bunch of "small PCBs" (is there a better name?) designed for hacking and prototyping, that already have the processor and a few other super-common things built in ... so you don't have to start *completely* from scratch.<br />
* [http://thinkcycle.org/ ThinkCycle] "ThinkCycle is a ... non-profit initiative ... supporting distributed collaboration towards design challenges facing underserved communities and the environment. ThinkCycle seeks to create a culture of open source design innovation"<br />
* Are [http://positron.org/projects/ the Positron projects] "open" enough to be mentioned? I especially liked the [http://positron.org/projects/acrylic_cases/ "Lasercut Acrylic Casebuilding Tutorial" ].<br />
* Is [http://wiki.vislab.usyd.edu.au/moinwiki/PuckControl/BuildingThePuck the Vislab puck] suitable for this list?<br />
* [http://massmind.org/techref/piclist/pcbcontest.htm PICList & JAL_List free PCB contest] "this will encourage people to publish designs and get more good ideas out into the real world for everyone to see." (So, are these "open" circuits?)<br />
* http://ePanorama.net/ has a bunch of schematics and a web discussion forum. Are they "open" enough to mention here?<br />
* "Yet Another One-hand Keyboard" ( http://chordite.com/ ) "The firmware included in the download lets an Atmel AVR '2313 microcontroller interpret chords and talk to a PS/2 port." -- it's not completely open, but the license allows you to immediately download, for free, lots of technical information and a license to build up to 5 of your own. Building more than 5 requires some sort of payment to license the patent on the hardware configuration. (The software appears to be open source). There seems to be an associated Yahoo mailing list. What is an appropriate way to invite John W. McKown and others on the mailing list to use a wiki such as Open Circuits to maintain a FAQ?<br />
* [http://www.solorb.com/elect/ FC's Electronic Circuits] ?<br />
* [http://panvent.blogspot.com/ "Pandemic Ventilator Project"] asks: "Does Open Source Hardware Development Work?"<br />
* GSM SMS Controllers ( http://www.elektronika.ba/projekti/?akc=daj_projekt&idprojekt=6 ) "TwoWay Thing (GSM Controller v3) is a device that allows you to control appliances using SMS messages. There are also 4 inputs for connecting sensors so the device will send an alarm SMS or even call you to report an alarm condition. The device draws very little current and is being powered by phone’s battery which is a great thing. Nokia should be constantly charged or supplied with some sort of external power for long term operation."<br />
* Phone-call alarm alert ( http://www.elektronika.ba/projekti/?akc=daj_projekt&idprojekt=7 ) "After programming just supply power to the device. After pressing the button "Pokreni dojavu alarma" it will start to dial (tone or pulse, depending on the jumper setup). When the phone call is succesfully established, the called party should press pound key "#" to stop the device from calling another number or again."<br />
* SMS Box ( http://www.elektronika.ba/projekti/?akc=daj_projekt&idprojekt=9 ) "This device acts as interface between your microcontroller project and a GSM phone. It handles all modem data communication between the GSM phone and your micro-project. The best thing is that it decodes PDU into TEXT on the fly!"<br />
* GSM alarm alert - call ( http://www.elektronika.ba/projekti/?akc=daj_projekt&idprojekt=5 ) "Alerting alarm over via GSM network"<br />
* [http://linuxdevices.com/news/NS3871478989.html Bug Labs]: A startup is readying a modular, open source hardware/software system resembling a set of electronic Legos. Nov. 05, 2007 [http://www.buglabs.net/]<br />
* [http://picflow.sourceforge.net/ PIC flow meter and instrumentation modules]: Sensors, Gauges, Flow meter, data logging, connected by Grundfos Pumps inc. GENIbus over RS485.<br />
* Raphaël Assénat has [http://raphnet.net/electronique/electronique_en.php posted several electronics projects], including schematics. Several of them involve interfacing various "classic" video game controllers to USB. His [http://raphnet.net/electronique/cid/cid_en.php "Caller Id decoder"] is a nice example of adding just one more feature to something using a minimum of additional electronics.<br />
* [http://www.grandideastudio.com/portfolio/defcon-15-badge/ Grand Idea Studio] -- do these badges count as "open circuits"?<br />
<br />
== [[Other Projects | other project sites or links to projects]] ==<br />
<br />
May or may not be open, not much review material here, noted for the record, may be promoted in the future if they are outstanding in any way.<br />
<br />
<br />
[[Category:Projects]]</div>Yanhttp://www.opencircuits.com/index.php?title=Ethernet_Module&diff=16383Ethernet Module2008-09-24T07:44:42Z<p>Yan: /* Architecture */ adding smtp</p>
<hr />
<div>==Introduction==<br />
*let a device have the following capabilities<br />
**can be controlled by a general browser in a desktop computer<br />
**access a server by itself to providing data, such as: device model no., serial no., any application data, or send out email for any events.<br />
*This project aims to develop an Ethernet Module, to be used in conjunction with a 8/16 bits embedded system such as the [http://opencircuits.com/DsPIC30F_5011_Development_Board dsPic33F development board].<br />
*[{{SERVER}}/Ethernet_Module#Architecture Architecture]<br />
<br />
==Bug List==<br />
*DHCP<br />
**dhcp client fault from buffalo router<br />
**occasionally cannot access webserver with dhcp<br />
<br />
*DHCP<br />
**dhcp client fault from main router<br />
**occasionally cannot access webserver with dhcp<br />
**possible cause: module tries to get IP configuration when switching on and off too frequently. This causes the router to enter into an unknown state. Even using the static mode with the same IP cannot get Internet access properly. When wait for some time and switch on the module again, the router may have been "reset", and the connection is ok again.<br />
<br />
<br />
==ToDo List==<br />
*32kB constant limitations<br />
**see if webserver can be stored in flash in file system<br />
*SNMP<br />
**porting snmp to uip<br />
**reference to lwip<br />
*SMTP<br />
**some router cannot used SMTP module<br />
**the router return its own IP as DNS resolver, and it does support only parsing direct IP function<br />
**desktop applications (e.g. outlook, thunderbird, webmail) do not use DNS resolver (UDP application) to connect to the mail server, but use TCP/IP to do the job<br />
<br />
==Hardware==<br />
===Component List===<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
! Special Item !! Description !! Quantity<br />
|-valign="top"<br />
| [http://www.davicom.com.tw/big5/download/Data%20Sheet/DM9000A-DS-F01-101906.pdf DM9000AEP] || Ethernet Controller from [http://www.davicom.com.tw/eng/index.htm Davicom] || 1<br />
|-<br />
| [http://www.hanrun.com/hr/upfile/2_1_113.pdf HR911102A] || RJ45 Connector with Integrated Magnetics for 10/100 Base-TX || 1<br />
|-<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/21749F.pdf 93LC46B-I/SN] || 1K Serial EEPROM || 1 (Optional)<br />
|-<br />
| 25MHz Crystal || Crystal || 1<br />
|-<br />
| 22pF || For Crystal Use || 2<br />
|-<br />
| 220uF || For RXVDD25/TXVDD25 || 1<br />
|-<br />
| 49.9ohm || For RX+/RX-/TX+/TX- || 4<br />
|-<br />
| 6.8kohm || For BGRES/BGGND || 1<br />
|-<br />
| 510ohm || For LEDs|| 2<br />
|-<br />
|}<br />
<br />
===Circuit and PCB===<br />
in [http://chungyan5.no-ip.org/vc/?root=ethernet gEDA format]<br />
and its gEDA [http://www.opencircuits.com/PCB_Footprints#gEDA_Symbols_and_footprints sym and footprints]<br />
<br />
<br />
==Software Driver==<br />
*Download [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/dm9000a.c?root=freertos_posix&view=markup dm9000a.c]<br />
*Download [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/include/dm9000a.h?root=freertos_posix&view=markup dm9000a.h]<br />
*Base on [http://www.freertos.org/ FreeRTOS] and [http://opencircuits.com/DsPIC30F_5011_Development_Board dsPIC33 platform]<br />
*Using POSIX-like API:<br />
**'''int dmfe_open(int flags)''': initialize the Ethernet controller for 10MHz Half-Duplex<br />
**'''int dmfe_close()''': turn off the PHY layer<br />
**'''int dmfe_read(void)''': copy a packet to the default buffer<br />
**'''int dmfe_write(unsigned char device, unsigned char *buf, int count)''': copy count bytes of the data from buf and transmit<br />
**'''void dmfe_interrupt(void)''': process the transmit interrupt from DM9000A<br />
<br />
<br />
==TCP/IP Stack==<br />
*uIP and lwIP are light weight TCP/IP Stack designed for 8-bit/16-bit embedded systems.<br />
<br />
----<br />
<br />
===uIP===<br />
*Develped by Adam Dunkels of the Networked Embedded Systems group at the Swedish Institute of Computer Science.<br />
*[http://www.sics.se/~adam/uip/ uIP] is under the [http://www.sics.se/~adam/uip/index.php/License BSD-style license]<br />
====CVS Repository====<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
! Attribute !! Value<br />
|-valign="top"<br />
| Host || uip-stack.cvs.sourceforge.net<br />
|-<br />
| Repository Path || /cvsroot/uip-stack<br />
|-<br />
| Connection Type || pserver<br />
|-<br />
| User || anonymous<br />
|-<br />
|}<br />
*Changes made to CVS Repository (tag: HEAD v1.1)<br />
**'''uip.c'''<br />
***Comment out all DEBUG_PRINTF(...) in lines 1, 323, 910, 1015, 1070, 1863, 1868, 1869<br />
**'''uip.h'''<br />
***Change line 1070 to<br># define HTONS(n) (u16_t)(((((u16_t) (n)) << 8)&0xff00) | ((((u16_t) (n)) >> 8)&0x00ff))<br />
**'''psock.c'''<br />
***Change line 188 to<br>s->sendptr = (u8_t*) buf;<br />
***Change lines 276, 303 to<br>buf_setup(&psock->buf, (u8_t*)(psock->bufptr), psock->bufsize);<br />
***Change line 334 to<br>buf_setup(&psock->buf, (u8_t*)buffer, buffersize);<br />
<br />
====Porting====<br />
*Include the following files to use the uIP stack<br />
**timer.c<br />
**uip.c<br />
**uip_arp.c<br />
**psock.c<br />
*The following files have been created to port uIP 1.0 to dsPic33F development board using FreeRTOS<br />
*[http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/clock-arch.c?root=freertos_posix&view=markup clock-arch.c]: return the os tick counts since the system is turned on.<br />
*[http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/include/clock-arch.h?root=freertos_posix&view=markup clock-arch.h]: a constant specifying the number of os ticks in one second.<br />
*[http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/dspic33/rackmount/04_uip/include/uip-conf.h?root=freertos_posix&view=markup uip-config.h]: configuration for your application.<br />
<br />
----<br />
<br />
===lwIP===<br />
*[http://savannah.nongnu.org/projects/lwip/ lwIP] is a small independent implementation of uIP.<br />
*It is more powerful than uIP but requires more memory.<br />
*lwIP is under the [http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5 Modified BSD License]<br />
====CVS Repository====<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
! Attribute !! Value<br />
|-valign="top"<br />
| Host || cvs.savannah.nongnu.org<br />
|-<br />
| Repository Path || /sources/lwip<br />
|-<br />
| Connection Type || pserver<br />
|-<br />
| User || anonymous<br />
|-<br />
|}<br />
====Porting====<br />
*To be added<br />
<br />
<br />
==uIP Ethernet Application==<br />
<br />
===DHCP Client===<br />
*Enable UDP in "uip-config.h"<br />
#define UIP_CONF_UDP 1<br />
*Make sure your uip buffer size is large enough (DHCP messages from some servers can be more than 500 bytes). In my setting, I use 1536 in "uip-config.h"<br />
#define UIP_CONF_BUFFER_SIZE 1536<br />
*Include the dhcpc.h header file in "uip-config.h"<br />
#include "dhcpc.h"<br />
*Change PT_WAIT_UNTIL(...) to PT_YIELD_UNTIL(...) in line 259 and 276 in "dhcpc.c" [This is a known bug in dhcpc.c]<br />
*In your main loop, initialize your MAC address and DHCP if UIP_FIXEDADDR is 0 in "uip-opt.h", for example:<br />
int main(void)<br />
{<br />
uip_ipaddr_t ipaddr;<br />
struct timer periodic_timer, arp_timer;<br />
struct uip_eth_addr mac = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06};<br />
<br />
timer_set(&periodic_timer, CLOCK_SECOND / 2);<br />
timer_set(&arp_timer, CLOCK_SECOND * 10);<br />
<br />
tapdev_init();<br />
uip_init();<br />
<br />
uip_setethaddr(mac);<br />
dhcpc_init(&mac, 6);<br />
<br />
while(1){<br />
//normal codes goes here<br />
}<br />
}<br />
*Implement dhcpc_configured(). This function will be called after DHCP client has obtained an IP address. Basically, you have to at least set your IP address, subnet mask and default gateway, for example,<br />
void dhcpc_configured(const struct dhcpc_state *s)<br />
{<br />
uip_sethostaddr(s->ipaddr);<br />
uip_setnetmask(s->netmask);<br />
uip_setdraddr(s->default_router);<br />
<br />
//you can print your ip addr to your console/lcd to see if you get a valid ip address<br />
}<br />
*An example of using DHCP Client in the dsPic33F development board can be found [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/common/app_http.c?root=freertos_posix&view=markup here].<br />
<br />
===Web Server===<br />
*Include the "webserver.h" header file in "uip-config.h"<br />
#include "webserver.h"<br />
*Modify httpd-fs.h<br />
**HTTPD_FS_STATISTICS set to 0<br />
*Create a website using HTML tags with/without Javascript<br />
*Modify httpd-fs.c<br />
**changed #include "httpd-fsdata.c" to #include <httpd-fsdata.c> <br />
*Generate httpd-fsdata.c for your website by executing '''perl makefsdata''' under your web root directory.<br />
====add-on====<br />
*The Web Server included in uIP 1.0 has been designed to load/reload the entire page (either html/shtml files) in response to a HTTP GET command, e.g.<br />
GET /index.html HTTP/1.1<br />
GET /abc.shtml HTTP/1.1<br />
*As a result, if the webpage is required to refresh the dynamic data periodically, the surfing experience will be degraded by the large transfer of datastream.<br />
*In consideration of the above issue, a solution is proposed here, so that the webserver can handle this kind of cgi HTTP-request<br />
GET /abc.shtml?val=500.0&button=Set HTTP/1.1<br />
*Modify httpd.c<br />
**added #include "httpd-hget.h" in line 63<br />
**added httpd_hget(s->filename) in line 224<br />
*Create httpd-hget.h<br />
**added to generate dynamic pages, e.g. /abc.shtml?button=Refresh<br />
#ifndef __HTTPD_HGET_H__<br />
#define __HTTPD_HGET_H__<br />
extern void httpd_hget(char *name);<br />
#endif<br />
*Create httpd-hget.c<br />
**an example is shown [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/dspic33/rackmount/04_uip/uip/httpd-hget.c?root=freertos_posix&view=markup here]<br />
<br />
==SNMP Agent==<br />
*Simple Network Management Protocol (SNMP) is a standard protocol to access variables to remote device via the Internet.<br />
*It belongs to the Application Layer, as in HTTP.<br />
*If a device is SNMP compatible, any SNMP compatible host system can monitor and control that device.<br />
<br />
===Components in a SNMP System===<br />
*Network Management Station (NMS)<br />
**This is a client, initiating SNMP communication.<br />
**This can be a PC with an NMS software (e.g. [http://nino.sourceforge.net/nino/index.html NINO]), polling data from the SNMP agents periodically.<br />
*SNMP Agents<br />
**These are servers, responding to one or multiple NMS requests.<br />
*Management Information Base (MIB)<br />
**A special collection of variables managed by the SNMP agents.<br />
**MIB has a tree-like structure.<br />
**An Object Identifier (OID) is given for each node.<br />
**Data are stored at the end-nodes.<br />
**Private variables may be constructed under the "enterprise" sub-tree.<br />
**The OID for "enterprise" can be obtained from [http://www.iana.org/cgi-bin/enterprise.pl Internet Assigned Number Authority (IANA)].<br />
<br />
===Abstract Syntax Notation===<br />
*Each MIB variable contains several attributes, such as data type, access type and object identifier.<br />
*Abstract Syntax Notation version 1 (ASN.1) is a language to define these attributes in SNMP.<br />
<br />
<br />
==Architecture==<br />
+---------------------------------------------+--------------------+-------+<br />
Applications | Ethernet Application | GUI Application | ... |<br />
+--------+------+------+----------+------+----+ | |<br />
Web Libraries | Web | DHCP | SNMP | DNS | SMTP |... | | |<br />
| Server | | | Resolver | | | | |<br />
+--------+------+------+----------+------+----+ | |<br />
Socket API | Linux-like Socket | | |<br />
+---------------------------------------------+ | |<br />
TCP/IP Stack | uip | | |<br />
+---------------------------------------------+ | |<br />
| Ethernet Controller | | |<br />
+--------------------------------------+------+--------------------+-------+<br />
POSIX API | POSIX System Calls | POSIX Threads |<br />
+--------------------------------------+-----------------------------------+<br />
| Drivers | Task Scheduler |<br />
+--------------------------------------+-----------------------------------+<br />
<br />
==Reference==<br />
===DM9000A===<br />
*[http://www.davicom.com.tw/eng/products/dm9000a.htm DM9000A Description]<br />
*[http://www.davicom.com.tw/big5/download/Data%20Sheet/DM9000A-DS-F01-101906.pdf DM9000A Datasheet]<br />
*[http://www.davicom.com.tw/big5/download/AC/dm9000a/DM9000A%20circuit_EMI_052306.pdf Application Circuit]<br />
*[http://www.davicom.com.tw/big5/download/LayoutGuide/DM9000A_9010-LG-V11_031706.pdf Layout Guidelines]<br />
*[http://www.davicom.com.tw/big5/download/ApplicationNote/DM9000A%20Application%20Notes%20Ver%201_20_101906.pdf Application Note]<br />
*[http://www.davicom.com.tw/eng/download/Driver/driver_9000.htm DM9000A Official Drivers]<br />
===dsPic33F Development Board===<br />
*[http://opencircuits.com/DsPIC30F_5011_Development_Board dsPic33F Development Board]<br />
===uIP===<br />
*[http://www.sics.se/~adam/uip/index.php/Main_Page uIP Description]<br />
*[http://www.sics.se/~adam/uip/index.php/Documentation uIP Documentation]<br />
*[http://www.sics.se/~adam/uip/index.php/Download Download]<br />
*[http://sourceforge.net/cvs/?group_id=186227 CVS Repository]<br />
===lwIP===<br />
*[http://savannah.nongnu.org/projects/lwip/ lwIP Description]<br />
*[http://www.nongnu.org/lwip/ Documentation]<br />
===HTML===<br />
*[http://www.w3schools.com/default.asp W3 Schools]: Learning how to write HTML and JavaScript<br />
*[http://www.nvu.com/index.php Nvu]: Open source HTML Editor<br />
===SNMP===<br />
*[http://www.snmplink.org SNMP Link]: Information on SNMP Agents<br />
*[http://pen.iana.org/pen/PenApplication.page IANA]: Applying a Private Enterprise Number</div>Yanhttp://www.opencircuits.com/index.php?title=Ethernet_Module&diff=16382Ethernet Module2008-09-24T07:36:13Z<p>Yan: /* Introduction */ clarify the objective</p>
<hr />
<div>==Introduction==<br />
*let a device have the following capabilities<br />
**can be controlled by a general browser in a desktop computer<br />
**access a server by itself to providing data, such as: device model no., serial no., any application data, or send out email for any events.<br />
*This project aims to develop an Ethernet Module, to be used in conjunction with a 8/16 bits embedded system such as the [http://opencircuits.com/DsPIC30F_5011_Development_Board dsPic33F development board].<br />
*[{{SERVER}}/Ethernet_Module#Architecture Architecture]<br />
<br />
==Bug List==<br />
*DHCP<br />
**dhcp client fault from buffalo router<br />
**occasionally cannot access webserver with dhcp<br />
<br />
*DHCP<br />
**dhcp client fault from main router<br />
**occasionally cannot access webserver with dhcp<br />
**possible cause: module tries to get IP configuration when switching on and off too frequently. This causes the router to enter into an unknown state. Even using the static mode with the same IP cannot get Internet access properly. When wait for some time and switch on the module again, the router may have been "reset", and the connection is ok again.<br />
<br />
<br />
==ToDo List==<br />
*32kB constant limitations<br />
**see if webserver can be stored in flash in file system<br />
*SNMP<br />
**porting snmp to uip<br />
**reference to lwip<br />
*SMTP<br />
**some router cannot used SMTP module<br />
**the router return its own IP as DNS resolver, and it does support only parsing direct IP function<br />
**desktop applications (e.g. outlook, thunderbird, webmail) do not use DNS resolver (UDP application) to connect to the mail server, but use TCP/IP to do the job<br />
<br />
==Hardware==<br />
===Component List===<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
! Special Item !! Description !! Quantity<br />
|-valign="top"<br />
| [http://www.davicom.com.tw/big5/download/Data%20Sheet/DM9000A-DS-F01-101906.pdf DM9000AEP] || Ethernet Controller from [http://www.davicom.com.tw/eng/index.htm Davicom] || 1<br />
|-<br />
| [http://www.hanrun.com/hr/upfile/2_1_113.pdf HR911102A] || RJ45 Connector with Integrated Magnetics for 10/100 Base-TX || 1<br />
|-<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/21749F.pdf 93LC46B-I/SN] || 1K Serial EEPROM || 1 (Optional)<br />
|-<br />
| 25MHz Crystal || Crystal || 1<br />
|-<br />
| 22pF || For Crystal Use || 2<br />
|-<br />
| 220uF || For RXVDD25/TXVDD25 || 1<br />
|-<br />
| 49.9ohm || For RX+/RX-/TX+/TX- || 4<br />
|-<br />
| 6.8kohm || For BGRES/BGGND || 1<br />
|-<br />
| 510ohm || For LEDs|| 2<br />
|-<br />
|}<br />
<br />
===Circuit and PCB===<br />
in [http://chungyan5.no-ip.org/vc/?root=ethernet gEDA format]<br />
and its gEDA [http://www.opencircuits.com/PCB_Footprints#gEDA_Symbols_and_footprints sym and footprints]<br />
<br />
<br />
==Software Driver==<br />
*Download [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/dm9000a.c?root=freertos_posix&view=markup dm9000a.c]<br />
*Download [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/include/dm9000a.h?root=freertos_posix&view=markup dm9000a.h]<br />
*Base on [http://www.freertos.org/ FreeRTOS] and [http://opencircuits.com/DsPIC30F_5011_Development_Board dsPIC33 platform]<br />
*Using POSIX-like API:<br />
**'''int dmfe_open(int flags)''': initialize the Ethernet controller for 10MHz Half-Duplex<br />
**'''int dmfe_close()''': turn off the PHY layer<br />
**'''int dmfe_read(void)''': copy a packet to the default buffer<br />
**'''int dmfe_write(unsigned char device, unsigned char *buf, int count)''': copy count bytes of the data from buf and transmit<br />
**'''void dmfe_interrupt(void)''': process the transmit interrupt from DM9000A<br />
<br />
<br />
==TCP/IP Stack==<br />
*uIP and lwIP are light weight TCP/IP Stack designed for 8-bit/16-bit embedded systems.<br />
<br />
----<br />
<br />
===uIP===<br />
*Develped by Adam Dunkels of the Networked Embedded Systems group at the Swedish Institute of Computer Science.<br />
*[http://www.sics.se/~adam/uip/ uIP] is under the [http://www.sics.se/~adam/uip/index.php/License BSD-style license]<br />
====CVS Repository====<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
! Attribute !! Value<br />
|-valign="top"<br />
| Host || uip-stack.cvs.sourceforge.net<br />
|-<br />
| Repository Path || /cvsroot/uip-stack<br />
|-<br />
| Connection Type || pserver<br />
|-<br />
| User || anonymous<br />
|-<br />
|}<br />
*Changes made to CVS Repository (tag: HEAD v1.1)<br />
**'''uip.c'''<br />
***Comment out all DEBUG_PRINTF(...) in lines 1, 323, 910, 1015, 1070, 1863, 1868, 1869<br />
**'''uip.h'''<br />
***Change line 1070 to<br># define HTONS(n) (u16_t)(((((u16_t) (n)) << 8)&0xff00) | ((((u16_t) (n)) >> 8)&0x00ff))<br />
**'''psock.c'''<br />
***Change line 188 to<br>s->sendptr = (u8_t*) buf;<br />
***Change lines 276, 303 to<br>buf_setup(&psock->buf, (u8_t*)(psock->bufptr), psock->bufsize);<br />
***Change line 334 to<br>buf_setup(&psock->buf, (u8_t*)buffer, buffersize);<br />
<br />
====Porting====<br />
*Include the following files to use the uIP stack<br />
**timer.c<br />
**uip.c<br />
**uip_arp.c<br />
**psock.c<br />
*The following files have been created to port uIP 1.0 to dsPic33F development board using FreeRTOS<br />
*[http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/clock-arch.c?root=freertos_posix&view=markup clock-arch.c]: return the os tick counts since the system is turned on.<br />
*[http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/include/clock-arch.h?root=freertos_posix&view=markup clock-arch.h]: a constant specifying the number of os ticks in one second.<br />
*[http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/dspic33/rackmount/04_uip/include/uip-conf.h?root=freertos_posix&view=markup uip-config.h]: configuration for your application.<br />
<br />
----<br />
<br />
===lwIP===<br />
*[http://savannah.nongnu.org/projects/lwip/ lwIP] is a small independent implementation of uIP.<br />
*It is more powerful than uIP but requires more memory.<br />
*lwIP is under the [http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5 Modified BSD License]<br />
====CVS Repository====<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
! Attribute !! Value<br />
|-valign="top"<br />
| Host || cvs.savannah.nongnu.org<br />
|-<br />
| Repository Path || /sources/lwip<br />
|-<br />
| Connection Type || pserver<br />
|-<br />
| User || anonymous<br />
|-<br />
|}<br />
====Porting====<br />
*To be added<br />
<br />
<br />
==uIP Ethernet Application==<br />
<br />
===DHCP Client===<br />
*Enable UDP in "uip-config.h"<br />
#define UIP_CONF_UDP 1<br />
*Make sure your uip buffer size is large enough (DHCP messages from some servers can be more than 500 bytes). In my setting, I use 1536 in "uip-config.h"<br />
#define UIP_CONF_BUFFER_SIZE 1536<br />
*Include the dhcpc.h header file in "uip-config.h"<br />
#include "dhcpc.h"<br />
*Change PT_WAIT_UNTIL(...) to PT_YIELD_UNTIL(...) in line 259 and 276 in "dhcpc.c" [This is a known bug in dhcpc.c]<br />
*In your main loop, initialize your MAC address and DHCP if UIP_FIXEDADDR is 0 in "uip-opt.h", for example:<br />
int main(void)<br />
{<br />
uip_ipaddr_t ipaddr;<br />
struct timer periodic_timer, arp_timer;<br />
struct uip_eth_addr mac = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06};<br />
<br />
timer_set(&periodic_timer, CLOCK_SECOND / 2);<br />
timer_set(&arp_timer, CLOCK_SECOND * 10);<br />
<br />
tapdev_init();<br />
uip_init();<br />
<br />
uip_setethaddr(mac);<br />
dhcpc_init(&mac, 6);<br />
<br />
while(1){<br />
//normal codes goes here<br />
}<br />
}<br />
*Implement dhcpc_configured(). This function will be called after DHCP client has obtained an IP address. Basically, you have to at least set your IP address, subnet mask and default gateway, for example,<br />
void dhcpc_configured(const struct dhcpc_state *s)<br />
{<br />
uip_sethostaddr(s->ipaddr);<br />
uip_setnetmask(s->netmask);<br />
uip_setdraddr(s->default_router);<br />
<br />
//you can print your ip addr to your console/lcd to see if you get a valid ip address<br />
}<br />
*An example of using DHCP Client in the dsPic33F development board can be found [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/common/app_http.c?root=freertos_posix&view=markup here].<br />
<br />
===Web Server===<br />
*Include the "webserver.h" header file in "uip-config.h"<br />
#include "webserver.h"<br />
*Modify httpd-fs.h<br />
**HTTPD_FS_STATISTICS set to 0<br />
*Create a website using HTML tags with/without Javascript<br />
*Modify httpd-fs.c<br />
**changed #include "httpd-fsdata.c" to #include <httpd-fsdata.c> <br />
*Generate httpd-fsdata.c for your website by executing '''perl makefsdata''' under your web root directory.<br />
====add-on====<br />
*The Web Server included in uIP 1.0 has been designed to load/reload the entire page (either html/shtml files) in response to a HTTP GET command, e.g.<br />
GET /index.html HTTP/1.1<br />
GET /abc.shtml HTTP/1.1<br />
*As a result, if the webpage is required to refresh the dynamic data periodically, the surfing experience will be degraded by the large transfer of datastream.<br />
*In consideration of the above issue, a solution is proposed here, so that the webserver can handle this kind of cgi HTTP-request<br />
GET /abc.shtml?val=500.0&button=Set HTTP/1.1<br />
*Modify httpd.c<br />
**added #include "httpd-hget.h" in line 63<br />
**added httpd_hget(s->filename) in line 224<br />
*Create httpd-hget.h<br />
**added to generate dynamic pages, e.g. /abc.shtml?button=Refresh<br />
#ifndef __HTTPD_HGET_H__<br />
#define __HTTPD_HGET_H__<br />
extern void httpd_hget(char *name);<br />
#endif<br />
*Create httpd-hget.c<br />
**an example is shown [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/dspic33/rackmount/04_uip/uip/httpd-hget.c?root=freertos_posix&view=markup here]<br />
<br />
==SNMP Agent==<br />
*Simple Network Management Protocol (SNMP) is a standard protocol to access variables to remote device via the Internet.<br />
*It belongs to the Application Layer, as in HTTP.<br />
*If a device is SNMP compatible, any SNMP compatible host system can monitor and control that device.<br />
<br />
===Components in a SNMP System===<br />
*Network Management Station (NMS)<br />
**This is a client, initiating SNMP communication.<br />
**This can be a PC with an NMS software (e.g. [http://nino.sourceforge.net/nino/index.html NINO]), polling data from the SNMP agents periodically.<br />
*SNMP Agents<br />
**These are servers, responding to one or multiple NMS requests.<br />
*Management Information Base (MIB)<br />
**A special collection of variables managed by the SNMP agents.<br />
**MIB has a tree-like structure.<br />
**An Object Identifier (OID) is given for each node.<br />
**Data are stored at the end-nodes.<br />
**Private variables may be constructed under the "enterprise" sub-tree.<br />
**The OID for "enterprise" can be obtained from [http://www.iana.org/cgi-bin/enterprise.pl Internet Assigned Number Authority (IANA)].<br />
<br />
===Abstract Syntax Notation===<br />
*Each MIB variable contains several attributes, such as data type, access type and object identifier.<br />
*Abstract Syntax Notation version 1 (ASN.1) is a language to define these attributes in SNMP.<br />
<br />
<br />
==Architecture==<br />
+--------------------------------------------+--------------------+-------+<br />
Applications | Ethernet Application | GUI Application | ... |<br />
+--------+--------+---------+----------+-----+ | |<br />
Web Libraries | Web | DHCP | SNMP | DNS | ... | | |<br />
| Server | | | Resolver | | | |<br />
+--------+--------+---------+----------+-----+ | |<br />
Socket API | Linux-like Socket | | |<br />
+--------------------------------------------+ | |<br />
TCP/IP Stack | uip | | |<br />
+--------------------------------------------+ | |<br />
| Ethernet Controller | | |<br />
+--------------------------------------+-----+--------------------+-------+<br />
POSIX API | POSIX System Calls | POSIX Threads |<br />
+--------------------------------------+----------------------------------+<br />
| Drivers | Task Scheduler |<br />
+--------------------------------------+----------------------------------+<br />
<br />
<br />
==Reference==<br />
===DM9000A===<br />
*[http://www.davicom.com.tw/eng/products/dm9000a.htm DM9000A Description]<br />
*[http://www.davicom.com.tw/big5/download/Data%20Sheet/DM9000A-DS-F01-101906.pdf DM9000A Datasheet]<br />
*[http://www.davicom.com.tw/big5/download/AC/dm9000a/DM9000A%20circuit_EMI_052306.pdf Application Circuit]<br />
*[http://www.davicom.com.tw/big5/download/LayoutGuide/DM9000A_9010-LG-V11_031706.pdf Layout Guidelines]<br />
*[http://www.davicom.com.tw/big5/download/ApplicationNote/DM9000A%20Application%20Notes%20Ver%201_20_101906.pdf Application Note]<br />
*[http://www.davicom.com.tw/eng/download/Driver/driver_9000.htm DM9000A Official Drivers]<br />
===dsPic33F Development Board===<br />
*[http://opencircuits.com/DsPIC30F_5011_Development_Board dsPic33F Development Board]<br />
===uIP===<br />
*[http://www.sics.se/~adam/uip/index.php/Main_Page uIP Description]<br />
*[http://www.sics.se/~adam/uip/index.php/Documentation uIP Documentation]<br />
*[http://www.sics.se/~adam/uip/index.php/Download Download]<br />
*[http://sourceforge.net/cvs/?group_id=186227 CVS Repository]<br />
===lwIP===<br />
*[http://savannah.nongnu.org/projects/lwip/ lwIP Description]<br />
*[http://www.nongnu.org/lwip/ Documentation]<br />
===HTML===<br />
*[http://www.w3schools.com/default.asp W3 Schools]: Learning how to write HTML and JavaScript<br />
*[http://www.nvu.com/index.php Nvu]: Open source HTML Editor<br />
===SNMP===<br />
*[http://www.snmplink.org SNMP Link]: Information on SNMP Agents<br />
*[http://pen.iana.org/pen/PenApplication.page IANA]: Applying a Private Enterprise Number</div>Yanhttp://www.opencircuits.com/index.php?title=Ethernet_Module&diff=16374Ethernet Module2008-09-22T10:09:44Z<p>Yan: update intro.</p>
<hr />
<div>==Introduction==<br />
*This project aims to develop an Ethernet Module, to be used in conjunction with a 8/16 bits embedded system such as the [http://opencircuits.com/DsPIC30F_5011_Development_Board dsPic33F development board].<br />
*[{{SERVER}}/Ethernet_Module#Architecture Architecture]<br />
<br />
==Bug List==<br />
*DHCP<br />
**dhcp client fault from buffalo router<br />
**occasionally cannot access webserver with dhcp<br />
<br />
*DHCP<br />
**dhcp client fault from main router<br />
**occasionally cannot access webserver with dhcp<br />
**possible cause: module tries to get IP configuration when switching on and off too frequently. This causes the router to enter into an unknown state. Even using the static mode with the same IP cannot get Internet access properly. When wait for some time and switch on the module again, the router may have been "reset", and the connection is ok again.<br />
<br />
<br />
==ToDo List==<br />
*32kB constant limitations<br />
**see if webserver can be stored in flash in file system<br />
*SNMP<br />
**porting snmp to uip<br />
**reference to lwip<br />
*SMTP<br />
**some router cannot used SMTP module<br />
**the router return its own IP as DNS resolver, and it does support only parsing direct IP function<br />
**desktop applications (e.g. outlook, thunderbird, webmail) do not use DNS resolver (UDP application) to connect to the mail server, but use TCP/IP to do the job<br />
<br />
==Hardware==<br />
===Component List===<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
! Special Item !! Description !! Quantity<br />
|-valign="top"<br />
| [http://www.davicom.com.tw/big5/download/Data%20Sheet/DM9000A-DS-F01-101906.pdf DM9000AEP] || Ethernet Controller from [http://www.davicom.com.tw/eng/index.htm Davicom] || 1<br />
|-<br />
| [http://www.hanrun.com/hr/upfile/2_1_113.pdf HR911102A] || RJ45 Connector with Integrated Magnetics for 10/100 Base-TX || 1<br />
|-<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/21749F.pdf 93LC46B-I/SN] || 1K Serial EEPROM || 1 (Optional)<br />
|-<br />
| 25MHz Crystal || Crystal || 1<br />
|-<br />
| 22pF || For Crystal Use || 2<br />
|-<br />
| 220uF || For RXVDD25/TXVDD25 || 1<br />
|-<br />
| 49.9ohm || For RX+/RX-/TX+/TX- || 4<br />
|-<br />
| 6.8kohm || For BGRES/BGGND || 1<br />
|-<br />
| 510ohm || For LEDs|| 2<br />
|-<br />
|}<br />
<br />
===Circuit and PCB===<br />
in [http://chungyan5.no-ip.org/vc/?root=ethernet gEDA format]<br />
and its gEDA [http://www.opencircuits.com/PCB_Footprints#gEDA_Symbols_and_footprints sym and footprints]<br />
<br />
<br />
==Software Driver==<br />
*Download [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/dm9000a.c?root=freertos_posix&view=markup dm9000a.c]<br />
*Download [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/include/dm9000a.h?root=freertos_posix&view=markup dm9000a.h]<br />
*Base on [http://www.freertos.org/ FreeRTOS] and [http://opencircuits.com/DsPIC30F_5011_Development_Board dsPIC33 platform]<br />
*Using POSIX-like API:<br />
**'''int dmfe_open(int flags)''': initialize the Ethernet controller for 10MHz Half-Duplex<br />
**'''int dmfe_close()''': turn off the PHY layer<br />
**'''int dmfe_read(void)''': copy a packet to the default buffer<br />
**'''int dmfe_write(unsigned char device, unsigned char *buf, int count)''': copy count bytes of the data from buf and transmit<br />
**'''void dmfe_interrupt(void)''': process the transmit interrupt from DM9000A<br />
<br />
<br />
==TCP/IP Stack==<br />
*uIP and lwIP are light weight TCP/IP Stack designed for 8-bit/16-bit embedded systems.<br />
<br />
----<br />
<br />
===uIP===<br />
*Develped by Adam Dunkels of the Networked Embedded Systems group at the Swedish Institute of Computer Science.<br />
*[http://www.sics.se/~adam/uip/ uIP] is under the [http://www.sics.se/~adam/uip/index.php/License BSD-style license]<br />
====CVS Repository====<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
! Attribute !! Value<br />
|-valign="top"<br />
| Host || uip-stack.cvs.sourceforge.net<br />
|-<br />
| Repository Path || /cvsroot/uip-stack<br />
|-<br />
| Connection Type || pserver<br />
|-<br />
| User || anonymous<br />
|-<br />
|}<br />
*Changes made to CVS Repository (tag: HEAD v1.1)<br />
**'''uip.c'''<br />
***Comment out all DEBUG_PRINTF(...) in lines 1, 323, 910, 1015, 1070, 1863, 1868, 1869<br />
**'''uip.h'''<br />
***Change line 1070 to<br># define HTONS(n) (u16_t)(((((u16_t) (n)) << 8)&0xff00) | ((((u16_t) (n)) >> 8)&0x00ff))<br />
**'''psock.c'''<br />
***Change line 188 to<br>s->sendptr = (u8_t*) buf;<br />
***Change lines 276, 303 to<br>buf_setup(&psock->buf, (u8_t*)(psock->bufptr), psock->bufsize);<br />
***Change line 334 to<br>buf_setup(&psock->buf, (u8_t*)buffer, buffersize);<br />
<br />
====Porting====<br />
*Include the following files to use the uIP stack<br />
**timer.c<br />
**uip.c<br />
**uip_arp.c<br />
**psock.c<br />
*The following files have been created to port uIP 1.0 to dsPic33F development board using FreeRTOS<br />
*[http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/clock-arch.c?root=freertos_posix&view=markup clock-arch.c]: return the os tick counts since the system is turned on.<br />
*[http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/include/clock-arch.h?root=freertos_posix&view=markup clock-arch.h]: a constant specifying the number of os ticks in one second.<br />
*[http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/dspic33/rackmount/04_uip/include/uip-conf.h?root=freertos_posix&view=markup uip-config.h]: configuration for your application.<br />
<br />
----<br />
<br />
===lwIP===<br />
*[http://savannah.nongnu.org/projects/lwip/ lwIP] is a small independent implementation of uIP.<br />
*It is more powerful than uIP but requires more memory.<br />
*lwIP is under the [http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5 Modified BSD License]<br />
====CVS Repository====<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
! Attribute !! Value<br />
|-valign="top"<br />
| Host || cvs.savannah.nongnu.org<br />
|-<br />
| Repository Path || /sources/lwip<br />
|-<br />
| Connection Type || pserver<br />
|-<br />
| User || anonymous<br />
|-<br />
|}<br />
====Porting====<br />
*To be added<br />
<br />
<br />
==uIP Ethernet Application==<br />
<br />
===DHCP Client===<br />
*Enable UDP in "uip-config.h"<br />
#define UIP_CONF_UDP 1<br />
*Make sure your uip buffer size is large enough (DHCP messages from some servers can be more than 500 bytes). In my setting, I use 1536 in "uip-config.h"<br />
#define UIP_CONF_BUFFER_SIZE 1536<br />
*Include the dhcpc.h header file in "uip-config.h"<br />
#include "dhcpc.h"<br />
*Change PT_WAIT_UNTIL(...) to PT_YIELD_UNTIL(...) in line 259 and 276 in "dhcpc.c" [This is a known bug in dhcpc.c]<br />
*In your main loop, initialize your MAC address and DHCP if UIP_FIXEDADDR is 0 in "uip-opt.h", for example:<br />
int main(void)<br />
{<br />
uip_ipaddr_t ipaddr;<br />
struct timer periodic_timer, arp_timer;<br />
struct uip_eth_addr mac = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06};<br />
<br />
timer_set(&periodic_timer, CLOCK_SECOND / 2);<br />
timer_set(&arp_timer, CLOCK_SECOND * 10);<br />
<br />
tapdev_init();<br />
uip_init();<br />
<br />
uip_setethaddr(mac);<br />
dhcpc_init(&mac, 6);<br />
<br />
while(1){<br />
//normal codes goes here<br />
}<br />
}<br />
*Implement dhcpc_configured(). This function will be called after DHCP client has obtained an IP address. Basically, you have to at least set your IP address, subnet mask and default gateway, for example,<br />
void dhcpc_configured(const struct dhcpc_state *s)<br />
{<br />
uip_sethostaddr(s->ipaddr);<br />
uip_setnetmask(s->netmask);<br />
uip_setdraddr(s->default_router);<br />
<br />
//you can print your ip addr to your console/lcd to see if you get a valid ip address<br />
}<br />
*An example of using DHCP Client in the dsPic33F development board can be found [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/common/app_http.c?root=freertos_posix&view=markup here].<br />
<br />
===Web Server===<br />
*Include the "webserver.h" header file in "uip-config.h"<br />
#include "webserver.h"<br />
*Modify httpd-fs.h<br />
**HTTPD_FS_STATISTICS set to 0<br />
*Create a website using HTML tags with/without Javascript<br />
*Modify httpd-fs.c<br />
**changed #include "httpd-fsdata.c" to #include <httpd-fsdata.c> <br />
*Generate httpd-fsdata.c for your website by executing '''perl makefsdata''' under your web root directory.<br />
====add-on====<br />
*The Web Server included in uIP 1.0 has been designed to load/reload the entire page (either html/shtml files) in response to a HTTP GET command, e.g.<br />
GET /index.html HTTP/1.1<br />
GET /abc.shtml HTTP/1.1<br />
*As a result, if the webpage is required to refresh the dynamic data periodically, the surfing experience will be degraded by the large transfer of datastream.<br />
*In consideration of the above issue, a solution is proposed here, so that the webserver can handle this kind of cgi HTTP-request<br />
GET /abc.shtml?val=500.0&button=Set HTTP/1.1<br />
*Modify httpd.c<br />
**added #include "httpd-hget.h" in line 63<br />
**added httpd_hget(s->filename) in line 224<br />
*Create httpd-hget.h<br />
**added to generate dynamic pages, e.g. /abc.shtml?button=Refresh<br />
#ifndef __HTTPD_HGET_H__<br />
#define __HTTPD_HGET_H__<br />
extern void httpd_hget(char *name);<br />
#endif<br />
*Create httpd-hget.c<br />
**an example is shown [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/dspic33/rackmount/04_uip/uip/httpd-hget.c?root=freertos_posix&view=markup here]<br />
<br />
==SNMP Agent==<br />
*Simple Network Management Protocol (SNMP) is a standard protocol to access variables to remote device via the Internet.<br />
*It belongs to the Application Layer, as in HTTP.<br />
*If a device is SNMP compatible, any SNMP compatible host system can monitor and control that device.<br />
<br />
===Components in a SNMP System===<br />
*Network Management Station (NMS)<br />
**This is a client, initiating SNMP communication.<br />
**This can be a PC with an NMS software (e.g. [http://nino.sourceforge.net/nino/index.html NINO]), polling data from the SNMP agents periodically.<br />
*SNMP Agents<br />
**These are servers, responding to one or multiple NMS requests.<br />
*Management Information Base (MIB)<br />
**A special collection of variables managed by the SNMP agents.<br />
**MIB has a tree-like structure.<br />
**An Object Identifier (OID) is given for each node.<br />
**Data are stored at the end-nodes.<br />
**Private variables may be constructed under the "enterprise" sub-tree.<br />
**The OID for "enterprise" can be obtained from [http://www.iana.org/cgi-bin/enterprise.pl Internet Assigned Number Authority (IANA)].<br />
<br />
===Abstract Syntax Notation===<br />
*Each MIB variable contains several attributes, such as data type, access type and object identifier.<br />
*Abstract Syntax Notation version 1 (ASN.1) is a language to define these attributes in SNMP.<br />
<br />
<br />
==Architecture==<br />
+--------------------------------------------+--------------------+-------+<br />
Applications | Ethernet Application | GUI Application | ... |<br />
+--------+--------+---------+----------+-----+ | |<br />
Web Libraries | Web | DHCP | SNMP | DNS | ... | | |<br />
| Server | | | Resolver | | | |<br />
+--------+--------+---------+----------+-----+ | |<br />
Socket API | Linux-like Socket | | |<br />
+--------------------------------------------+ | |<br />
TCP/IP Stack | uip | | |<br />
+--------------------------------------------+ | |<br />
| Ethernet Controller | | |<br />
+--------------------------------------+-----+--------------------+-------+<br />
POSIX API | POSIX System Calls | POSIX Threads |<br />
+--------------------------------------+----------------------------------+<br />
| Drivers | Task Scheduler |<br />
+--------------------------------------+----------------------------------+<br />
<br />
<br />
==Reference==<br />
===DM9000A===<br />
*[http://www.davicom.com.tw/eng/products/dm9000a.htm DM9000A Description]<br />
*[http://www.davicom.com.tw/big5/download/Data%20Sheet/DM9000A-DS-F01-101906.pdf DM9000A Datasheet]<br />
*[http://www.davicom.com.tw/big5/download/AC/dm9000a/DM9000A%20circuit_EMI_052306.pdf Application Circuit]<br />
*[http://www.davicom.com.tw/big5/download/LayoutGuide/DM9000A_9010-LG-V11_031706.pdf Layout Guidelines]<br />
*[http://www.davicom.com.tw/big5/download/ApplicationNote/DM9000A%20Application%20Notes%20Ver%201_20_101906.pdf Application Note]<br />
*[http://www.davicom.com.tw/eng/download/Driver/driver_9000.htm DM9000A Official Drivers]<br />
===dsPic33F Development Board===<br />
*[http://opencircuits.com/DsPIC30F_5011_Development_Board dsPic33F Development Board]<br />
===uIP===<br />
*[http://www.sics.se/~adam/uip/index.php/Main_Page uIP Description]<br />
*[http://www.sics.se/~adam/uip/index.php/Documentation uIP Documentation]<br />
*[http://www.sics.se/~adam/uip/index.php/Download Download]<br />
*[http://sourceforge.net/cvs/?group_id=186227 CVS Repository]<br />
===lwIP===<br />
*[http://savannah.nongnu.org/projects/lwip/ lwIP Description]<br />
*[http://www.nongnu.org/lwip/ Documentation]<br />
===HTML===<br />
*[http://www.w3schools.com/default.asp W3 Schools]: Learning how to write HTML and JavaScript<br />
*[http://www.nvu.com/index.php Nvu]: Open source HTML Editor<br />
===SNMP===<br />
*[http://www.snmplink.org SNMP Link]: Information on SNMP Agents<br />
*[http://pen.iana.org/pen/PenApplication.page IANA]: Applying a Private Enterprise Number</div>Yanhttp://www.opencircuits.com/index.php?title=DsPIC30F_5011_Development_Board&diff=16096DsPIC30F 5011 Development Board2008-08-08T08:47:41Z<p>Yan: /* Java Environment Setup */ for linux(ubunut) platform as well</p>
<hr />
<div>==Introduction==<br />
<br />
===Features of dsPIC30F5011===<br />
*2.5 to 5V <br />
*Up to 30MIPs<br />
*High current/sink source I/O pins: 25mA<br />
*DSP Instruction Set<br />
*Dual programming techniques: ICSP and RTSP<br />
*UART: up to 2 modules<br />
*I<sup>2</sup>C: up to 1Mbps<br />
*10-bit A/D, 1.1 Msps <br />
*12-bit A/D, 200 ksps<br />
*44K flash (66Kb), 4Kb RAM, 1Kb EEPROM<br />
*No DAC<br />
*Pin-to-pin compatible with other dsPICs<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 1.1 Comparison with Compatible dsPICs<br />
! dsPic !! Price<br>US$ !! MIPs<br />
! Flash<br>(kB)!! RAM<br>(kB) !! EEPROM<br>(kB)<br />
! I/O !! ADC<br>12-bit !! IC !! OC !! Motor<br>Ctrl !! Timers<br />
! QEI !! UART !! SPI !! I2C !! CAN !! Codec<br />
|- <br />
| 30F5011 || 5.91 || 30<br />
| 66 || 4 || 1<br />
| 52 || 16 || 8 || 8 || 0 || 5x16bit<br>2x32bit<br />
| 0 || 2 || 2 || 1 || 2 || 1<br />
|-<br />
| 30F6011A || 7.73 || 30<br />
| 132 || 6 || 2<br />
| 52 || 16 || 8 || 8 || 0 || 5x16bit<br>2x32bit<br />
| 0 || 2 || 2 || 1 || 2 || 0<br />
|-<br />
| 30F6012A || 7.85 || 30<br />
| 144 || 8 || 4<br />
| 52 || 16 || 8 || 8 || 0 || 5x16bit<br>2x32bit<br />
| 0 || 2 || 2 || 1 || 2 || 1<br />
|- <br />
| 33FJ128GP206 || 4.62 || 40<br />
| 128 || 8 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 1 || 0 || 1<br />
|-<br />
| 33FJ128GP306 || 4.81 || 40<br />
| 128 || 16 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 2 || 0 || 1<br />
|-<br />
| 33FJ128GP706 || 5.49 || 40<br />
| 128 || 16 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 2 || 2 || 1<br />
|-<br />
| 33FJ128MC506 || 4.97 || 40<br />
| 128 || 8 || 0<br />
| 53 || 16 || 8 || 8 || 8 || 9x16bit<br>4x32bit<br />
| 1 || 2 || 2 || 2 || 1 || 0<br />
|-<br />
| 33FJ128MC706 || 5.38 || 40<br />
| 128 || 16 || 0<br />
| 53 || 16 || 8 || 8 || 8 || 9x16bit<br>4x32bit<br />
| 1 || 2 || 2 || 2 || 1 || 0<br />
|-<br />
| 33FJ256GP506 || 6.11 || 40<br />
| 256 || 16 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 2 || 1 || 1<br />
|-<br />
|}<br />
<br />
===Web Page===<br />
*[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2529&param=en024856 Microchip Official Website]<br />
<br />
===Forum===<br />
*[http://direct.forum.microchip.com/default.aspx Microchip]: Official forum by Microchip<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=49 MPLAB ICD 2]: Subforum on ICD 2 programmer<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=57 MPLAB IDE]: Subforum on IDE<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=101 MPLAB C30 Compiler, ASM30, Link30 forum]: Subforum on C compiler. Refer to [http://ww1.microchip.com/downloads/en/DeviceDoc/C30_Users_Guide_51284e.pdf MPLAB C30 C Compiler User's Guide] Chapter 3<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=153 dsPIC30F Topics]: Subformum on dsPIC30F<br />
*[http://www.gnupic.org/ GNUPIC]: Discussion on PIC in Linux Systems<br />
**[http://www.linuxhacker.org/cgi-bin/ezmlm-cgi?1:dds:5443#b Debian]<br />
*[http://www.htsoft.com/forum/all/ubbthreads.php/Cat/0/C/6 HI-TECH Software Forum]: Discussion on dsPICC, a C compiler developed by HI-TECH<br />
*[http://piclist.com/techref/piclist/index.htm PICList]: Discussion on older PIC systems (not dsPIC)<br />
*[http://groups.google.com/group/pickit-devel PicKit]: Discussion on PICkit/PICkit 2 programmers<br />
*[http://sourceforge.net/forum/forum.php?forum_id=382005 FreeRTOS Real Time Kernel]: Open Discussion and Support on FreeRTOS <br />
<br />
===References===<br />
*dsPIC30F<br />
**[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2574 dsPIC30F Family Reference Manual Sections]: Contains detailed descriptions on dsPIC30F register definitions and example codes<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80169E.pdf dsPIC30F Family Reference Manual Errata (Use with revision 70046B only)]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70116F.pdf dsPIC30F5011, dsPIC30F5013 Data Sheet]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80210e.pdf dsPIC30F5011/5013 Rev. A1/A2 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80223D.pdf dsPIC30F5011/5013 Rev. A3 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70102G.pdf Flash Programming Specification]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70157B.pdf dsPIC30F Programmer's Reference Manual]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80170a.pdf dsPIC30F Programmer's Reference Manual Errata (use with revision DS70030E only)]<br />
<br />
*dsPIC33F<br />
**[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2573 dsPIC33F Family Reference Manual Sections]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70165E.pdf dsPIC33F Family Data Sheet]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80279B.pdf dsPIC33F Rev. A2 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80306A.pdf dsPIC33FJXXXGPX06/X08/X10 Rev. A2 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70152C.pdf Flash Programming Specification]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70172A.pdf dsPIC30F to dsPIC33F Conversion Guidelines]<br />
*ICD2 Programmer<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/51331B.pdf ICD2 User's Guide] <br />
*MPLAB<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/51519B.pdf MPLAB IDE User's Guide]<br />
*C30 Compiler<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/C30_Users_Guide_51284e.pdf MPLAB C30 C Compiler User's Guide]: Contains commands for using pic30-elf-gcc <br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/16bit_Language_Tool_Libraries_51456c.pdf 16-bit Language Tools Libraries]: Contains summaries and examples of using DSP libraries, standard C libraries and device libraries<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/Asm30_Link_Util_51317e.pdf MPLAB ASM30, MPLAB LINK30 and Utilities User's Guide]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/51322d.pdf dsPIC30F Language Tools Quick Reference Card]<br />
<br />
===Code Examples===<br />
*[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1408 Microchip Example Codes for dsPic]<br />
<br />
<br />
==Programming Methods==<br />
*There are 2 programming methods: In-Circuit Serial Programming (ICSP) and Run-Time Self-Programming (RTSP)<br />
*ICSP allows the devices to be programmed after being placed in a circuit board.<br />
*RTSP allows the devices to be programmed when an embedded program is already in operation.<br />
<br />
===ICSP: External Programmer (ICD2)===<br />
*Two types of ICSP are available: '''ICSP''' and '''Enhanced ICSP'''. Both of them require setting MCLR# to V<sub>IHH</sub> (9V – 13.25V).<br />
*Standard ICSP<br />
**Use external programmer (e.g. MPLAB<sup>®</sup> ICD 2, MPLAB<sup>®</sup> PM3 or PRO MATE<sup>®</sup> II) only.<br />
**Required low-level programming to erase, program and verify the chip.<br />
**Slower, because codes are serially executed.<br />
**Program memory can be erased using ''Normal-Voltage'' (4.5 – 5.5V) or ''Low-Voltage'' (2.5V – 4.5V).<br />
<br />
*Enhanced ICSP<br />
**Use external programmer and '''Programming Executive''' (PE).<br />
**PE is stored in the on-chip memory.<br />
**PE allows faster programming.<br />
**PE can be downloaded to the chip by external programmer using the standard ICSP method.<br />
**PE contains a small command set to erase, program and verify the chip, avoiding the need of low-level programming.<br />
<br />
====Hardware Interface====<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.1 Pin Used by ICSP<br />
! Pin Label !! Function !! Pin Number<br />
|- <br />
| MCLR# || Programming Enable|| 7<br />
|-<br />
| V<sub>DD</sub> || Power Supply || 10, 26, 38, 57<br />
|-<br />
| V<sub>SS</sub> || Ground || 9, 25, 41, 56<br />
|- <br />
| PGC || Serial Clock || 17<br />
|-<br />
| PGD || Serial Data || 18<br />
|-<br />
|}<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.2 Available Programmers in the Market<br />
! Product Name<br />
! Interface with PC<br />
! Interface with Device<br />
! Price (US)<br />
! Postage (US)<br />
! Total (US)<br />
|- <br />
| [http://direct.www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en010046&part=DV164005 MPLAB<sup>®</sup> ICD 2]<br />
| USB or RS232<br />
| [http://www.microchip.com/Microchip.WWW.SecureSoftwareList/secsoftwaredownload.aspx?device=en010046&lang=en&ReturnURL=http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en010046&part=DV164005# 6-PIN RJ-12 connector]<br />
| $159.99<br />
| -<br />
| -<br />
|-<br />
| [http://www.etekronics.com/product_info.php?cPath=24&products_id=48 Full Speed USB Microchip ICD2<br> Debugger and Programmer]<br />
| USB<br />
| 6-PIN ICSP connector<br>6-PIN RJ-12 connector<br />
| $72.00<br />
| $12.00<br />
| $84.00<br />
|-<br />
| [http://www.etekronics.com/product_info.php?cPath=24&products_id=47 Mini Microchip Compatible ICD2<br> Debugger and Programmer]<br />
| RS232<br />
| 6-PIN ICSP connector<br>6-PIN RJ-12 connector<br />
| $45.00<br />
| $10.00<br />
| $55.00<br />
|-<br />
| [http://www.inexglobal.com/microcontroller.php ICDX30]<br />
| RS232<br />
| 6-pin RJ-11<br />
| $51.00<br />
| $47.46<br />
| $98.46<br />
|-<br />
| *[http://www.sure-electronics.net Clone Microchip ICD2] (Now Using)<br />
| USB<br />
| 6-pin flat cables<br />
| $30.00<br />
| $12.00<br />
| $42.00<br />
|-<br />
|}<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.3 DIY ICD 2 Programmer Circuit<br />
! Source !! Schematic !! PIC16F877A Bootloader<br />
|- <br />
| [http://membres.lycos.fr/silicium31/Electronique/PIC/FreeIcdEnglish.htm Patrick Touzet]<br />
| [http://membres.lycos.fr/silicium31/Electronique/PIC/ICD2%20V1.3.pdf Yes]<br />
| [http://membres.lycos.fr/silicium31/Electronique/PIC/ICD2_FW.zip HEX]<br />
|-<br />
| [http://www.nebadje.org/doku.php?id=neblab:icd2clone Nebadje]<br />
| [http://people.ee.ethz.ch/~jbiveron/nebadje/ICD2_DOC.pdf Yes]<br />
| [http://people.ee.ethz.ch/~jbiveron/nebadje/ICD2_FW.zip Zip]<br />
|-<br />
|}<br />
<br />
====Software Interface====<br />
*The program can be written and compiled in an Integrated Development Environment (IDE) using either Assembly or C. The complied codes are then loaded to the device through the external programmer.<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.4 Summary of IDE<br />
! Product Name !! Features !! OS !! Price (US$)<br />
|- <br />
| [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en019469&part=SW007002 MPLAB<sup>®</sup> IDE]<br />
| Assembler Only<br />
| Windows<br />
| Free<br />
|-<br />
| [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en010065&part=SW006012 MPLAB<sup>®</sup> C30]<br />
| Assembler and C-Compiler<br />
| Windows<br />
| $895.00 (Free student version<sup>1</sup>)<br />
|-<br />
| [http://linux.softpedia.com/get/Science-and-Engineering/Electronic-Design-Automation-EDA-/Piklab-8099.shtml Piklab 0.12.0]<br />
| Assembler and C-Compiler<br />
| Linux<br />
| Free<sup>2</sup><br />
|}<br />
# Full-featured for the first 60 days. After 60 days, some code optimization functions are disabled. The compiler will continue to function after 60 days, but code size may increase.<br />
# The current version supports external programmer ICD 2, but not yet tested.<br />
<br />
===RTSP: COM Port (Bootloader)===<br />
*RTSP works in normal voltage (MCLR# no need to raise to V<sub>IHH</sub>).<br />
*No literature has mentioned the incorporation of Programming Executive (PE). Presumably, since Enhanced ICSP needs to set MCLR# to V<sub>IHH</sub>, RTSP cannot use PE.<br />
*Refer to [http://www.opencircuits.com/DsPIC30F_5011_Development_Board#Bootloader_Development bootloader section].<br />
<br />
<br />
==IC Requirements==<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 3.1 IC Requirements<br />
! Part No. !! Description <br />
! Min Temp !! Max Temp !! Min Volt !! Max Volt !! Typ Cur !! Max Cur<br />
|-valign="top"<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/70116F.pdf dsPIC30F5011-30I/PT] || uP <br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 2.5V <sup>[1]</sup>|| 5.5V<br />
| 145mA || 217mA<br />
|-<br />
| [http://datasheets.maxim-ic.com/en/ds/MAX3222-MAX3241.pdf MAX3232ESE] || RS232 driver<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 3.0V || 5.5V<br />
| 0.3mA || 1.0mA<br />
|-<br />
| [http://www.national.com/ds.cgi/DS/DS3695.pdf DS3695N] || RS485 driver<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 4.75V || 5.25V<br />
| 42mA || 60mA<br />
|-<br />
| [http://focus.ti.com/lit/ds/symlink/dac6574.pdf DAC6574IDGS] || 10-bit Quad-DAC I<sup>2</sup>C<br />
| -40<sup>o</sup>C || 105<sup>o</sup>C<br />
| 2.7V || 5.5V<br />
| 0.6mA || 0.9mA<br />
|-<br />
| [http://www.semiconductors.philips.com/acrobat/datasheets/74HC_HCT14_3.pdf 74HC14D] || Quad-Schmitt Trigger<br />
| -40<sup>o</sup>C || 125<sup>o</sup>C<br />
| 2.0V || 6.0V<br />
| || 0.02mA<br />
|-<br />
| '''Overall''' || <br />
| '''-40<sup>o</sup>C''' || '''85<sup>o</sup>C'''<br />
| '''4.75V''' || '''5.25V'''<br />
| || '''<300mA <sup>[2]</sup>'''<br />
|-<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/70165E.pdf dsPIC33FJ128GP306-I/PT] || uP <br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 3.0V <sup>[1]</sup>|| 3.6V<br />
| 74mA || 250mA<br />
|-<br />
| [http://www.analog.com/UploadedFiles/Data_Sheets/ADM3485E.pdf ADM3485EARZ] || RS485 driver<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 3.0V || 3.6V<br />
| 1.1mA || 2.2mA<br />
|-<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/21203N.pdf 24LC256-I/SN] || 256kBits I2C EEPROM<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 2.5V || 5.5V<br />
| 400uA || 3mA<br />
|-<br />
| [http://www.national.com/ds.cgi/LM/LM3940.pdf LM3940IMP-3.3] || 5V-3.3V Regulator<br />
| -40<sup>o</sup>C || 125<sup>o</sup>C<br />
| 5.0V || 7.5V<br />
| 10mA || 250mA<br />
|-<br />
|}<br />
#Minimum voltage measured is 3.3V (with 2 LEDs blinking) running at 30MHz.<br />
#Measured current at 5V is 180mA (with 2 LEDs blinking only)<br />
<br />
<br />
==Development Environment==<br />
<br />
===Windows===<br />
<br />
[[Image:PIC_setup_win.JPG]]<br />
<br />
*C-Compiler, Assembler and Linker are under GNU license.<br />
**MPLAB C30 C Compiler (*.c -> *.s)<br />
**MPLAB ASM30 Assembler (*.s -> *.o)<br />
**MPLAB LINK30 Linker (*.o -> *.bin)<br />
<br />
*PA optimizer, simulator, runtime libraries, header files, include files, and linker scripts are not covered by GNU. Reference is [http://direct.forum.microchip.com/tm.aspx?m=107208 here].<br />
<br />
*Microchip has integrated ASM30, LINK30, assembly header files, linker scripts in MPLAB IDE, which is free for download.<br />
*MPLAB C30 costs US$895. A 60-day free student version is also available. After 60-days, the optimizer is automatically disabled, while other tools can still function properly. Refer to Table 2.4.<br />
<br />
*C-libraries contained in C30 includes (Refer to [http://ww1.microchip.com/downloads/en/DeviceDoc/16bit_Language_Tool_Libraries_51456c.pdf 16-Bit Language Tools Libraries] from Microchip).<br />
<br />
<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 4.1 C Libraries in MPLAB C30<br />
! Library !! Directory <br>(\\Microchip\MPLAB C30) !! Major functions<br />
|-valign="top"<br />
| DSP Library <br>(e.g. libdsp-coff.a)<br />
| \lib <br> \src\dsp <br> \support\h<br />
| Vector, Matrix, Filter, etc.<br />
|-valign="top"<br />
| 16-Bit Peripheral Libraries <br>(e.g. libp30F5011-coff.a)<br />
| \lib <br> \src\peripheral <br> \support\h<br />
| ADC12, IOPort, UART, I<sup>2</sup>C, etc.<br />
|-valign="top"<br />
| Standard C Libraries <br>(e.g. libc-coff.a, libm-coff.a, libpic-coff.a)<br />
| \lib <br> \src\libm <br> \include<br />
| stdio.h, time.h, float.h, math.h, <br />
|-valign="top"<br />
| MPLAB C30 Built-in Functions<br />
| none<br />
| _buildin_addab, _buildin_add, _buildinmpy, etc<br />
|-<br />
|}<br />
<br />
===Linux===<br />
<br />
[[Image:PIC_setup_linux.JPG]]<br />
<br />
*C Compiler, Assembler and Linker are under GNU license.<br />
**The code can be downloaded from Microchip at [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en023073 here].<br />
**Current MPLAB ASM30 Assembler: v2.04<br />
**Current MPLAB C30 Compiler: v2.04<br />
<br />
*[http://gcc.gnu.org/ml/gcc/2005-02/msg01144.html John Steele Scott] has made templates that can be readily used by Debian-based systems. <br />
*For v1.32, the necessary conversion to *.deb has been done already at [http://noel.feld.cvut.cz/dspic/ here].<br />
**Download '''pic30-1.32-debian.tar.bz2''' for Template v1.32.<br />
**Download '''pic30-binutils_1.32-1_i386.deb''' for the assember.<br />
**Download '''pic30-gcc_1.32-1_i386.deb''' for the compiler.<br />
*For v2.00<br />
**goto http://www.baycom.org/~tom/dspic/<br />
**download pic30-gcc-2.00-1.i386.rpm and pic30-binutils-2.00-1.i386.rpm<br />
**convert to deb files<br />
**install these two deb files<br />
*For v3.01, convert the Toolchain following instructions at [http://www.nabble.com/Debian-templates-for-dsPIC-build-toolchain-3.01-tf4308624.html here]<br />
**Pre-install these packages: dpkg-dev, debhelper, bison, flex, sysutils, gcc-3.3, fakeroot<br />
***cmd: '''sudo apt-get install dpkg-dev debhelper bison flex sysutils gcc-3.3 fakeroot'''<br />
**Download and unzip template: '''pic30-3.01.tar.bz2'''<br />
**Download assembler: '''mplabalc30v3_01_A.tar.gz'''. Save under /pic30-3.01/pic30-binutils-3.01/upstream/<br />
**Download c-compiler: '''mplabc30v3_01_A.tgz'''. Save under /pic30-3.01/pic30-gcc-3.01/upstream/<br />
**Install MPLAB_C30_v3_01-StudentEdition under Windows<br />
**Copy directories /include, /lib, /support, and /bin/c30_device.info to pic30-3.01/pic30-support-3.01/upstream/<br />
**Pack pic30-binutils into deb file<br />
***goto /pic30-3.01/pic30-binutils-3.01/<br />
***type cmd: '''dpkg-buildpackage -rfakeroot -b'''<br />
**Pack pic30-gcc-3.01 into deb file<br />
***goto /pic30-3.01/pic30-gcc-3.01/<br />
***type cmd: '''dpkg-buildpackage -rfakeroot -b'''<br />
**Pack pic30-gcc-3.01 into deb file<br />
***goto /pic30-3.01/pic30-support-3.01/<br />
***type cmd: '''dpkg-buildpackage -rfakeroot -b'''<br />
**install pic30-binutils_3.01-1_i386.deb<br />
***type cmd: '''sudo dpkg -i pic30-binutils_3.01-1_i386.deb'''<br />
**install pic30-gcc_3.01-1_i386.deb<br />
***type cmd: '''sudo dpkg -i pic30-gcc_3.01-1_i386.deb'''<br />
**install pic30-support_3.01-1_all.deb<br />
***type cmd: '''sudo dpkg -i pic30-support_3.01-1_all.deb'''<br />
*'''Important Note''': Only the compiler is free. The header files and library are owned by Microchip. <br />
**Thomas Sailer suggested to download the Student version of C30 compiler and then build the libraries without source code. A package template for Fedora system is available [http://www.baycom.org/~tom/dspic/ here].<br />
**Instructions for filling the upstream direction is available [http://forum.microchip.com/printable.aspx?m=139360 here].<br />
**Alteratively, [https://gna.org/projects/pic30-libc/ Stephan Walter] has started a project to develop C Runtime Library for dsPIC. <br />
***Current libraries in version 0.1.1 include: assert.h, cdefs.h, ctype.h, errno.h, inttypes.h, stdint.h, stdio.h, stdlib.h, string.h<br />
<br />
*Burning Program Codes to Target Board<br />
#Use 'dspicprg and dspicdmp' utilities developed by [http://homerreid.ath.cx/misc/dspicprg/ Homer Reid] to burn hex code (*.hex) to devices. See Reference [http://forum.microchip.com/tm.aspx?m=94243 here]. Through serial port only?<br />
#Use [http://piklab.sourceforge.net/ Piklab IDE]. Details on file format not known.<br />
#Use [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en019469&part=SW007002 MPLAB IDE] to burn hex code (*.hex) to devices.<br />
<br />
===Code Optimization===<br />
*Below is a comparsion between different optimization levels for the project including drivers for 2 projects.<br />
<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 4.2 Comparison between differnt optimization levels<br />
! Optimization !! Description !! Project 1<br>Code Size<br>(byte) !! Project 1<br>Data Usage<br>(byte) !! Project 2<br>Code Size<br>(byte) !! Project 2<br>Data Usage<br>(byte)<br />
|-valign="top"<br />
| O0 <br />
| No optimization<br>Fastest Compilation<br />
| 6222 (9%) || 178 (4%) || 26,037 (38%) || 710 (17%)<br />
|-valign="top"<br />
| O1 <br />
| Optimize<br> Tries to reduce code size and execution time.<br />
| 4473 (6%) || 178 (4%) || 22,290 (32%) || 710 (17%)<br />
|-valign="top"<br />
| O2 <br />
| Optimize even more<br> Performs nearly all supported optimizations <br>that do not involve a space-speed trade-off. <br>Increases both compilation time and the <br>performance of the generated code.<br />
| 4422 (6%) || 178 (4%) || 21,993 (32%) || 710 (17%)<br />
|-valign="top"<br />
| O3 <br />
| Optimize yet more. <br>O3 turns on all optimizations specified by O2 <br>and also turns on the inline-functions option.<br />
| 4485 (6%) || 178 (4%) || 22,176 (32%) || 710 (17%)<br />
|-valign="top"<br />
| Os <br />
| Optimize for size. <br>Os enables all O2 optimizations that do not <br>typically increase code size. It also performs <br>further optimizations designed to reduce code <br>size.<br />
| 4356 (6%) || 178 (4%) || 21,885 (32%) || 710 (17%)<br />
|-<br />
|}<br />
<br />
<br />
==Software Architecture==<br />
+--------+--------+--------+--------+--------+<br />
Application | Task 1 | Task 2 | Task 3 | Task 4 | Task 5 |<br />
+--------+--------+--------+--------+--------+<br />
| POSIX API |<br />
+-------------------+------------------------+<br />
OS | Coroutine | FreeRTOS Scheduler |<br />
+-------------------+------------------------+<br />
| Drivers |<br />
+------+-----+-----+--------+-------+--------+<br />
Hardware | UART | ADC | DAC | EEPROM | PWM | TIMERS | <br />
+------+-----+-----+--------+-------+--------+<br />
*Currently, operating system is based on [http://www.freertos.org/ FreeRTOS] incorporating coroutine developed by [http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html Simon Tatham]<br />
*Software Drivers are to be developed to allow users at Application Level to use the hardware (e.g. ADC, DAC, UART, EEPROM etc) through the OS.<br />
*The interface between the drivers and the OS is based on [http://www.die.net/doc/linux/man/man2/ POSIX standard] (e.g. open(), write(), read(), ioctl(), usleep() etc).<br />
*The most up-to-date development can be found at repository [http://chungyan5.no-ip.org/vc/?root=freertos_posix freertos_posix]<br />
<br />
<br />
==[[Programming Tips]]==<br />
<br />
==Bootloader Development==<br />
<br />
===Concepts===<br />
*Programming with ICSP is useful when the target board is produced in batch. The producer can download a program even when the chip is on the target board.<br />
*However, ICSP requires an external programmer.<br />
*To allow the user to change the program after production but without the need of an external programmer, bootloader becomes useful.<br />
*Bootloader is a small program installed via ICSP. Everytime the device is reset, the bootloader is run first. The bootloader first detects the default serial channel whether the user wishes to download a new program to the device. If so, the bootloader will pause there, and wait for the user to download the hex file from the PC. The hex file is written to the device via RTSP instructions in the bootloader. If a new download is not necessary, the bootloader redirects to the previously installed user's program.<br />
*The disadvantage of bootloaders is that they consume some of the memory of the device.<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 7.1 Free bootloaders for dsPIC<br />
! Developer<br />
! Source<br />
! Platform<br />
! User Guide<br />
! Remarks<br />
|- valign="top"<br />
| [http://www.ingenia-cat.com/index.php?lang=en ingenia]<br />
| [http://www.ingenia-cat.com/download/iBL.s Assembly]<br />
| [http://www.ingenia-cat.com/download/ingeniadsPICbootloader1.1.zip Windows]<br />
| [http://www.ingenia-cat.com/reference/pdf/iBL.UG.V1.2.pdf pdf]<br />
| <br />
*Works for all dsPIC supporting RTSP<br />
*Auto baudrate detection<br />
*Use about 1.15% of the flash memory space (0xAFFF-0xAE00)/(0xAFFF-0x0100)<br />
*Development of Linux platform is underway<br />
*Modification of code for dsPIC30F5011 is successful<br />
|-valign="top"<br />
| [http://www.etc.ugal.ro/cchiculita/software/picbootloader.htm Tiny]<br />
| [http://www.etc.ugal.ro/cchiculita/software/tinybld191.zip Assembly]<br />
| Windows<br />
| [http://www.etc.ugal.ro/cchiculita/software/tinybldusage.htm Web]<br />
| <br />
*By default, only supports 601X, 601X, 401X, 2010<br />
*Smaller code size than ingenia, but not as easy to modify<br />
|-valign="top"<br />
| [http://www.via.si/software/dsPIC_bootloader/ Elektronika]<br />
| [http://www.via.si/software/dsPIC_bootloader/data/ Hex]<br />
| Windows<br />
| [http://www.via.si/software/dsPIC_bootloader/data/README.txt txt]<br />
| <br />
*Only works for dsPIC30F6014 serial port UART2 at baudrate 57600<br />
|-<br />
|}<br />
<br />
===dsPicBootloader===<br />
<br />
*The bootloader developed by ingenia is open source and it has been modified (see below) to suit our development using dsPic30f5011.<br />
*The bootloader (hereafter called dsPicBootloader) employs the following settings:<br />
# Use U2ART channel<br />
# Use FRC, PLL16<br />
# For 5011, the bootloader is located between 0x00AE00 to 0x00AFFE (512bytes). Refer to C:\Program Files\Ingenia\ingeniadsPICbootloader\ibl_dspiclist.xml after installing the GUI interface.<br />
*Changes made to [http://www.ingenia-cat.com/download/iBL.s assembly code] includes:<br />
1. including p30f5011.gld and p30f5011.inc<br />
.include "p30f5011.inc"<br />
2. changing the config code of UART #0x8420 -> #0x8020<br />
; Uart init<br />
mov '''#0x8020''', W0 ; W0 = 0x8020 -> 1000 0000 0010 0000b<br />
mov W0, U2MODE ; Enable UART, AutoBaud and 8N1<br />
clr U2STA<br />
3. changing the start address 0xAE00 - 0x0100 = 0AD00<br />
.equ CRC, W4<br />
.equ ACK, 0x55<br />
.equ NACK, 0xFF<br />
.equ USER_ADDRESS, 0x0100<br />
.equ START_ADDRESS, '''0xAD00''' ; Relative to 0x0100<br />
4. using Internal FRC and PLL16<br />
config __FOSC, CSW_FSCM_OFF & '''FRC_PLL16''' ;Turn off clock switching and<br />
;fail-safe clock monitoring and<br />
;use the Internal Clock as the<br />
;system clock<br />
5. disabling MCLR (optional)<br />
config __FBORPOR, PBOR_ON & BORV_27 & PWRT_16 & '''MCLR_DIS'''<br />
;Set Brown-out Reset voltage and<br />
;and set Power-up Timer to 16msecs<br />
6. changing all the related registers of U1ART to U2ART, all U1XXX => U2XXX<br />
'''U2MODE, U2STA, U2BRG, U2RXREG, U2TXREG'''<br />
7. changing all the related registers of IC1 to IC2, all IC1XXX => IC2XXX<br />
'''IC2CON, #IC2IF, #IC2IE'''<br />
<br />
===dsPicProgrammer (Java-based Multi-Platformed)===<br />
*Ingenia developed a programmer (PC-side) that works only in Windows environment. The project for Linux environment is currently suspended.<br />
*A simple programmer (hereafter called dsPicProgrammer) written in Java based on the library developed by [http://www.rxtx.org/ RXTX] has been developed here. The programmer supports both Linux and Windows environments, and may be used as a substitution for the official programmer developed by ingenia.<br />
*The programmer has the following specification and limitations:<br />
#Can be used on both Linux and Windows platforms.<br />
#Adjustable baudrate (9600bps to 57600bps<sup>[1]</sup>).<br />
#Support programming of dsPIC30F5011 and dsPIC33FJ128GP306<sup>[2]</sup> devices (Developers may add your devices).<br />
#Protection against overwriting bootloader codes on devices.<br />
#Detection if application program does not have its reset() at user's code start address.<br />
#Reprogramming can be done without powering down the target board, provided the user's program is compliant to that stated below.<br />
#Target board will run the user's program after programming is done.<br />
#Can be used with USB-Serial Cables. Below is a list of tested cable:<br />
::[http://www.prolific.com.tw/eng/Products.asp?ID=59 Prolific PL-2303 USB to Serial Bridge Controller]: [http://www.prolific.com.tw/eng/downloads.asp?ID=31 Driver download]<br />
'''NOTE:'''<br><br />
[1] from version 1.5.2 onwards, the baudrate is increased to 115200bps.<br><br />
[2] only dsPIC30 devices are compatible with the ingenia's programmer. For dsPIC33 devices, the protocol has been modified due to the increased flash size, and the dsPIC33 bootloader can only work with dsPicProgrammer.<br />
<br />
===Special Consideration===<br />
*The bootloader assumes that the user program starts at address 0x100. This is usually the case, but there are always exceptions.<br />
*To ensure that the user program always starts at address 0x100, you can create a customized linker script and customized reset() function as follows:<br />
:*Copy and modify the file named "crt0.s" from the directory "C:\Program Files\Microchip\MPLAB C30\src\pic30" to the project directory and include it.<br />
.section .reset, code //previously .section .libc, code <br />
:*Copy and modify the linkerscript for the device (e.g. p30f5011.gld) to the project directory and include it.<br />
.text __CODE_BASE :<br />
{<br />
*(.reset); //<-insert this line here<br />
*(.handle);<br />
*(.libc) *(.libm) *(.libdsp); /* keep together in this order */<br />
*(.lib*);<br />
*(.text);<br />
} >program<br />
<br />
===Communication Protocol===<br />
<br />
+-------------------+ +-------------------+----------------+<br />
| dsPicProgrammer | | dsPicBootloader | User's Program |<br />
+-------------------+ +-------------------+----------------+<br />
| PC | | Target dsPic |<br />
+-------------------+ +------------------------------------+<br />
| COM PORT |=============| UART |<br />
+-------------------+ +------------------------------------+<br />
<br />
* '''Stage 1: User's Configuation'''<br />
**Select a COM port channel<br />
**Select a baudrate<br />
**Select the user hex file<br />
java -jar dsPicProgrammer.jar COM1 19200 foo.hex<br />
* '''Stage 2: Resetting Target Device'''<br />
**dsPicProgrammer sends a Break character (pull UART-TX to low logic, which is normally high).<br />
**User's program on dsPic detects the break character and reset the chip<br />
::NOTE: The user's program is expected to have the following code in order to enable this function. Otherwise, the target board must be restarted manually.<br />
void _ISR _U2RXInterrupt(void)<br />
{<br />
//No Framming error<br />
if( U2STAbits.FERR == 0)<br />
{<br />
//Normal procedure<br />
}<br />
//Framming error<br />
else<br />
{<br />
if ( U2STAbits.URXDA ){<br />
unsigned char data;<br />
data = (unsigned char) U2RXREG;<br />
if(data == 0x00){<br />
// A break char has been received: <br />
// U2RX has been pulled to zero for more than 13 bits<br />
// This is used to reboot the pic<br />
mdelay(800); //wait for break character to clear<br />
asm("reset"); //software reset<br />
}<br />
} <br />
}<br />
_U2RXIF = 0; //Clear the flag<br />
}<br />
* '''Stage 3: Entering Ingenia's Protocol'''<br />
** Transmission is conducted in 8N1, i.e. 8-bit, no parity, 1 stop-bit<br />
** Communication Protocol is reviewed in [http://www.ingenia-cat.com/reference/pdf/iBL.UG.V1.2.pdf ingenia bootloader user's guide] section 2.1.3. The following summarises the key steps on the PC side (Refer also to section 2.2.2).<br />
::#Autobaud rate detection: dsPicProgrammer continuously sends a character "U" [0x55] via COM port and waits for an acknowledgment character "U", [ACK] = [0x55]<br />
::#Version Control: dsPicProgrammer sends the command character [0x03]. On success, dsPicProgrammer receives 3 characters i) Major Version ii) Minor Version iii) Acknowledgment [0x55]<br />
::#Device ID Monitoring: dsPicProgrammer sends the read command character [0x01] + 24-bit address [High][Medium][Low] (0xFF0000). Then, it receives 4-byte data [High][Medium][Low][ACK]<br />
::#Load the user hex file and check integrity<br />
::#Start Programming: dsPicProgrammer issues the write command character [0x02] + 24-bit address [High][Medium][Low]+ Number of bytes [N] + [data 0] + [data 1] + ... + [data N-1] + [CRC]=(INTEL HEX8 Checksum - Sum modulo 256) and receives [ACK] or [NACK] = [0xFF]<br />
::NOTE: Writing is in row mode access (i.e. erase and write a whole row, each row has 32 instructions, or 96 bytes because each instruction has 24 bits)<br />
* '''Stage 4: Goto User's Program'''<br />
**dsPicProgrammer sends the goto user code command [0x0F]<br />
<br />
<br />
==USB-RS232 Bridge==<br />
<br />
*As USB ports are becoming more and more common, COM ports and Parallel ports may be redundant in the next few years. This section explore the possibilities of programming the target board through a USB port.<br />
*There are two options:<br />
#Use an external USB/RS232 adaptor, the driver will emulate a virtual COM port, such as [http://www.prolific.com.tw/eng/downloads.asp?ID=31 Prolific] and [http://www.ftdichip.com/Drivers/VCP.htm FDTI]. Ingenia has tested its bootloader with some USB-232 manufacturers (silabs, FTDI, etc..). However, the programming failed with our Prolific adapter. Application program may use [http://java.sun.com/products/javacomm/ JavaComm API] (javax.comm) and/or [http://www.rxtx.org/ RXTX] to drive the COM port.<br />
#Modified the bootloader program on PC to support USB communication. e.g. using [http://jusb.sourceforge.net/ jUSB] and [http://javax-usb.org/ JSR-80] (javax.usb). External circuits such as PIC18F4550 and MAX232 are required.<br />
<br />
|--User's App.--|-------Device Manager------|-------USB-RS232 Interface------|---dsPIC---|<br />
Option 1:<br />
+-------------+ +----------+ +----------+ +---+ +------------+ +-----+ +--------+<br />
| Application |--| JavaComm |--| Virtual |==|USB|--| FDTI |--|RS232|==| Target |<br />
| Program | | RXTX | | COM Port | +---+ | Circuitary | +-----+ | Board |<br />
+-------------+ +----------+ +----------+ +------------+ +--------+<br />
Option 2:<br />
+-------------+ +--------+ +---+ +------------+ +-----+ +--------+<br />
| Application |----------| JSR-80 |==========|USB|--| PIC18F4550 |--|RS232|==| Target |<br />
| Program | | jUSB | +---+ | MAX232 | +-----+ | Board |<br />
+-------------+ +--------+ +------------+ +--------+<br />
<br />
*Currently, when RXTX is incorporated with JavaComm API, operating systems supported include Linux, Windows, Mac OS, Solaris and other operating systems. On the other hand, jUSB and JSR-80 only works for linux.<br />
<br />
===FDTI Chipset===<br />
*FT232RL communicates with PC via USB to provide 1 UART channel.<br />
*Datasheet can be downloaded [http://www.ftdichip.com/Documents/DataSheets/DS_FT232R.pdf here]. <br />
**Refer to Fig. 11 (Page 19) for Bus Powered Configuration.<br />
**Refer to Fig. 16 (Page 24) for for UART TTL-level Receive [RXD -> 1], Transmit [TXD -> 4], Transmit Enable [CBUS2/TXDEN -> 3]. Omit Receive Enable [CBUS3/PWREN#] and use [CBUS2/TXDEN -> 2] <br />
**Refer to Fig. 15 (Page 23) for LED Configuration: [CBUS0/TXLED#] and [CBUS1/RXLED#]<br />
*Virtual COM Port Drivers can be downloaded [http://www.ftdichip.com/Drivers/VCP.htm here].<br />
<br />
<br />
==Programming the Device==<br />
<br />
===Requirements===<br />
*Hardware<br />
#PC with COM port (Windows XP Installed for MPLAB)<br />
#ICD2 Programmer<br />
#Target Board<br />
#5V Power Supply<br />
<br />
*Software<br />
#[http://ww1.microchip.com/downloads/en/DeviceDoc/MP750.zip MPLAB IDE v7.50]: v7.60 is not compatible with our current [http://www.sure-electronics.com/ ICD2 Programmers]. There are consistent "Devices cannot be founded" warnings.<br />
#[http://chungyan5.no-ip.org/websvn/listing.php dsPicProgrammer] ('''dsPicProgrammer.jar''')<br />
#[http://users.frii.com/jarvi/rxtx/download.html RXTX driver]: download and upzip rxtx-2.1-7-bins-r2.zip (Final)<br />
<br />
*Files<br />
#[http://chungyan5.no-ip.org/websvn/listing.php dsPicBootloader] ('''bl_5011.hex'''). Original assembly code by ingenia can be downloaded from [http://www.ingenia-cat.com/download/iBL.s here].<br />
#Application hex file (e.g. '''app.hex''')<br />
<br />
===Loading Bootloader (Once only)===<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 9.1 Loading Bootloader<br />
! Step !! Remarks <br />
|-valign="top"<br />
| Install [http://ww1.microchip.com/downloads/en/DeviceDoc/MP750.zip MPLAB IDE] || <br />
*Do '''NOT''' connect ICD 2 (via USB) to PC<br />
*Execute '''MPLAB vX.XX Install.exe'''<br />
|-valign="top"<br />
| Install USB Driver ||<br />
*Follow the instruction in (C:\Program Files\Microchip\MPLAB IDE\ICD2\Drivers\Ddicd2.htm)<br />
|-valign="top"<br />
| Select Target Chip ||<br />
*Run MPLAB IDE on PC<br />
*Select: Configure>Select Devices...<br />
*Choose dsPIC30F5011<br />
|-valign="top"<br />
| Target <-> ICD 2 ||<br />
*Use six pin cable. Beware of the pin assignments. Only pin 1 - 5 should be used.<br />
*Place Jumper on target board (if any). The Jumper connects target V<sub>cc</sub> to ICD 2.<br />
*Do '''NOT''' power-up the target.<br />
|-valign="top"<br />
| ICD 2 <-> PC ||<br />
*Plug-in ICD 2 to PC via USB cable<br />
*Power-up the target.<br />
*Select: Programmer>Select Programmer>MPLAB ICD 2<br />
*If this is the first time the ICD 2 is connected to PC, MPLAB IDE will automatically download the required OS to ICD 2, wait until it has finished<br />
*If you have not connected and powered up the target, you might see Warnings on invalid device IDs, and/or running self tests.<br />
*See results of self test if necessary: Programmer>Settings, Status Tab. Refer to [http://ww1.microchip.com/downloads/en/DeviceDoc/51331B.pdf ICD2 User's Guide] Chapter 7.<br />
|-valign="top"<br />
| Load Bootloader ||<br />
*Select: File>Import...<br />
*Select '''bl_5011.hex'''<br />
|-valign="top"<br />
| Start Programming ||<br />
*Select: Programmer>Program<br />
|-valign="top"<br />
| Finishing ||<br />
*Power-down the Taget<br />
*Select: Programmer>Select Programmer>None<br />
*Unplug USB cable<br />
|-<br />
|}<br />
<br />
===Loading Firmware===<br />
<!--using Firefox-File-Page_Setup-Format-Scale-85% to print --><br />
====Java Environment Setup====<br />
*Download and install the latest JDK or JRE<br />
**Available from [http://java.sun.com/javase/downloads/index.jsp Sun Microsystems] (e.g. JDK 6 Update 3)<br>[[Image:1 1 java.JPG]]<br><br />
*Download and Extract RXTX Driver <br />
**Available from [http://users.frii.com/jarvi/rxtx/download.html RXTX] <br />
**File: rxtx-2.1-7-bins-r2.zip (Final)<br />
**Extract the files using software such as WinRAR<br>[[Image:1 2 rxtx.JPG]]<br><br />
*Copy RXTXcomm.jar to<br />
**For Windows users, C:\Program Files\Java\X\lib\ext (under the latest jre, e.g. X = jre1.6.0_03)<br />
**For Linux users, /usr/lib/jvm/java-version/jre/lib/ext<br>[[Image:1 3 rxtxcomm.JPG]]<br><br />
*Copy rxtxSerial.dll/librxtxSerial.so to<br />
**For Windows users, C:\Program Files\Java\X\bin (under the lastest jre, e.g. X = jre1.6.0_03)<br />
**For Linux users, /usr/lib/jvm/java-version/jre/lib/[machine type] (i386 for instance)<br>[[Image:1 4 rxtxserial.JPG]]<br><br />
*Download dsPicProgrammer <br />
**Available from [http://chungyan5.no-ip.org/vc here]<br />
**Expand the latest tag under dsPicProgrammer<br />
**File: dsPicProgrammer.jar<br>[[Image:1 5 dspicprogrammer.JPG]]<br><br />
**Save the file (dsPicProgrammer.jar) and your hex file (foo.hex) to your local directory (e.g. C:\dsPicProgrammer\)<br>[[Image:1 6 dspicprogrammer2.JPG]]<br><br />
=====directly download this [http://chungyan5.no-ip.org/open_data/electronic_computer/platforms/dspic/dsPicProgrammer/dsPicProgrammer1.5.2.zip package]=====<br />
<br />
====Download Firmware====<br />
*Start a Command Prompt<br />
**Start -> Run<br>[[Image:2 1 run.JPG]]<br><br />
**Enter cmd<br>[[Image:2 2 cmd.JPG]]<br><br />
*Run dsPicProgrammer<br />
**Make sure your device is connected through a "Direct RS232 Cable" to PC Serial Port. <br />
**Change to the directory where dsPicProgrammer.jar is located and run the command:<br />
***[path/to/java/]java -Djava.library.path=[path/to/rxtxlib] -jar dsPicProgrammer.jar COM1 57600 foo.hex<br />
****for example, jre\bin\java -Djava.library.path=.\rxtx\bin -jar dspicProgrammer.jar COM1 57600 foo.hex<br />
***Or directly using dsPicProgrammer.bat COM1 57600 foo.hex(Windows)<br />
***java -jar dsPicProgrammer.jar /dev/ttyS0 57600 foo.hex (Linux)<br />
:::where COM1 is your COM Port ID<br />
:::57600 is communication speed [in bps]<br />
:::foo.hex is your firmware new file<br />
::[[Image:2 3 command.JPG]]<br />
**When the program prompt you for an input, press y:<br>[[Image:2 4 prompt.JPG]]<br><br />
**If communication can be established, you should see something like this:<br>[[Image:2 5 progress.JPG]]<br><br />
**Wait until programming is completed.<br>[[Image:2 6 complete.JPG]]<br><br />
**after all completed, power OFF your device, then power ON again, enjoy your new updated.<br />
<br />
====Troubleshooting====<br />
*Invalid COM Port<br />
**In case of selecting an invalid COM port, you should see the error message:<br>gnu.io.NoSuchPortException: Choosing COM Port Error<br>[[Image:3 1 com err.JPG]]<br><br />
*Missing firmware file<br />
**In case of selecting a firmware file that does not exist, you should see the error message:<br>java.io.FileNotFoundException: foo1.hex <The system cannot find the file specified><br>[[Image:3 2 file err.JPG]]<br><br />
*Missing RXTX driver<br />
**In case of missing the RXTX driver, you should see the error message:<br>Exception in thread “main” java.lang.NoClassDefFoundError: gnu/io/UnsupportedCommOperationException<br>[[Image:3 3 rxtx err.JPG]]<br><br />
<br />
==Remote Access==<br />
*At the moment, local devices (e.g. EEPROM, ADC, DAC, etc.) can only be accessed locally through POSIX functions such as open(), read(), write(), ioctl().<br />
*However, a client may need to access these devices on a remote server. This section reviews the background and gives some ideas on its possible implementation.<br />
<br />
===Requirements===<br />
*A remote file access protocol, to transfer "files" (i.e. device's data) such as:<br />
#[http://en.wikipedia.org/wiki/FTP File Transfer Protocol] (FTP): Required files are copied from sever to client for manipulation<br />
#[http://en.wikipedia.org/wiki/Remote_Shell Remote Shell] (RSH): Required files are copied from sever to client for manipulation<br />
#[http://en.wikipedia.org/wiki/Network_File_System_%28Sun%29 Network File System] (NFS): Required files are manipulated on sever<br />
*An API to access files using a selected protocol, such as:<br />
#[http://www.die.net/doc/linux/man/man2/lam_rfposix.2.html lam_rfposix]: A POSIX-like remote file service for Local Area Multicomputer<br />
#API employed by VxWorks: [http://en.wikipedia.org/wiki/VxWorks VxWorks] is a Unix-like real-time operating system, commonly used for embedded systems.<br />
<br />
===API Reference for VxWorks===<br />
*Reference:<br />
**[http://www.windriver.com/vxworks/ VxWorks Official Website]<br />
**[http://www-cdfonline.fnal.gov/daq/commercial/ OS Libraries API Reference]<br />
*Related Libraies<br />
**netDrv (netDrv.h): an API using FTP or RSH<br />
**nfsDrv (nfsDrv.h): an API using NFS<br />
<br />
<br />
==Conversion to dsPIC33F Devices==<br />
*This section discusses the conversion required from dsPIC30F5011 to dsPIC33FJ128GP306.<br />
*Refer to official document [http://ww1.microchip.com/downloads/en/DeviceDoc/70172A.pdf dsPIC30F to dsPIC33F Conversion Guidelines] (DS70172A).<br />
*Note that this section does not mainly intend to introduce the new functionalities of dsPIC33F devices. It only serves the purpose to summarise the major (if not minimum) changes required to port the setup of dsPIC30 to dsPIC33 devices.<br />
<br />
===Hardware===<br />
*dsPIC33 operates at voltage of 3.3V. A voltage regulator, such as [http://www.national.com/ds.cgi/LM/LM3940.pdf LM3940] can be used to convert 5V supply to 3.3V.<br />
*A 1uF capacitor has to be placed at pin 56 (previously V<sub>SS</sub>, now V<sub>DDCORE</sub>).<br />
<br />
===Software===<br />
<br />
====Configuration Bits====<br />
<br />
----<br />
*dsPIC33 can operate at 40MIPs at maximum. To configure the device using internal FRC, replace the configuration bits setting as follows:<br />
_FOSCSEL(FNOSC_FRCPLL); // FRC Oscillator with PLL<br />
_FOSC(FCKSM_CSDCMD & OSCIOFNC_ON & POSCMD_NONE); <br />
// Clock Switching and Fail Safe Clock Monitor is disabled<br />
// OSC2 Pin Function: OSC2(RC15) as Digital IO<br />
// Primary Oscillator Mode: Disabled<br />
_FWDT(FWDTEN_OFF); // Watchdog Timer Enabled/disabled by user software <br />
*Configure on-chip PLL at runtime as follows (at start of main function):<br />
_PLLDIV = 38; // M=40: PLL Feedback Divisor bits<br />
CLKDIV = 0; // N1=2: PLL VCO Output Divider Select bits<br />
// N2=2: PLL Phase Detector Input Divider bits<br />
OSCTUN = 22; // Tune FRC oscillator, if FRC is used; <br />
// 0: Center frequency (7.37 MHz nominal)<br />
// 22: +8.25% (7.98 MHz)<br />
RCONbits.SWDTEN = 0; // Disable Watch Dog Timer<br />
while(OSCCONbits.LOCK != 1); // Wait for PLL to lock<br />
<br />
====UART====<br />
<br />
----<br />
*No change is required.<br />
<br />
====I2C====<br />
<br />
----<br />
*dsPIC33 supports upto 2 I<sup>2</sup>C devices. As a result, replace all I<sup>2</sup>C related registers with xxI2Cyy to xxI2C'''1'''yy. For examples:<br />
_SI2C1IF = 0; //Clear Slave interrupt<br />
_MI2C1IF = 0; //Clear Master interrupt<br />
_SI2C1IE = 0; //Disable Slave interrupt<br />
_MI2C1IE = 0; //Disable Master interrupt<br />
I2C1BRG = I2C_BRG; // Configure Baud rate<br />
I2C1CONbits.I2CEN = 1;<br />
...<br />
etc.<br />
<br />
====ADC====<br />
<br />
----<br />
*The ADC in dsPic33 is significantly different from that in dsPic30. Specifically, ADC in dsPic33 uses DMA to buffer the adc data. Replace the open, interrupt routine, add and remove codes as follows:<br />
<br />
unsigned int adc_bufA[ADC_MAX_CH] __attribute__((space(dma),aligned(256)));<br />
unsigned int adc_bufB[ADC_MAX_CH] __attribute__((space(dma),aligned(256)));<br />
unsigned int* ADC16Ptr; //Pointer to ADC register buffer, <br />
unsigned char adc_ch_select = 0; //Pointer to channel to be read from<br />
unsigned char adc_data_ready = 0; //Indicate if RAM data is ready for output<br />
unsigned int which_dma = 0; //indicate which adc_buf to be used<br />
<br />
void adc_open(void)<br />
{<br />
// Configure interrupt<br />
_AD1IF = 0; //clear ADC interrupt flag<br />
_AD1IE = 0; //disable adc interrupt<br />
AD1CHSbits.CH0NA = 0;<br />
// Configure analog i/o <br />
_TRISB0 = 1;<br />
_TRISB1 = 1; <br />
AD1PCFG = 0xFFFC; //Enable AN0 (Vref+) and AN1 (Vref-)<br />
AD1PCFGH = 0xFFFF; //AN16-AN31: Disabled<br />
// Configure scan input channels <br />
AD1CSSL = 0x0003; //0 => Skip, 1 => Scan<br />
AD1CSSH = 0x0000; //Skipping AN16-AN31<br />
// ADCCON4:<br />
AD1CON4bits.DMABL = 0; // Each buffer contains 1 word<br />
// ADCCON3:<br />
AD1CON3bits.SAMC = 1; //1TAD for sampling time<br />
AD1CON3bits.ADRC = 0; //Use system clock<br />
AD1CON3bits.ADCS = ADC_ADCS; //each conversion requires 14TAD<br />
// ADCCON2:<br />
AD1CON2bits.VCFG = 3; //External Vref+, Vref-<br />
AD1CON2bits.CSCNA = 1; //Scan input<br />
AD1CON2bits.SMPI = 1; //2 channels are scanned<br />
// ADCCON1:<br />
AD1CON1bits.FORM = 0; //[0:integer]; [2 fractional]; [3 siged fractional]<br />
AD1CON1bits.SSRC = 7; //auto covert, using internal clock source<br />
AD1CON1bits.ASAM = 1; //auto setting of SAMP bit<br />
AD1CON1bits.AD12B = 1; //12-bit, 1-channel ADC operation<br />
AD1CON1bits.ADDMABM = 0; // DMA buffers are built in scatter/gather mode<br />
AD1CON1bits.ADON = 1; // Turn on the A/D converter<br />
// DMA0 Configuration:<br />
DMA0CONbits.AMODE = 2; // Configure DMA for Peripheral indirect mode<br />
DMA0CONbits.MODE = 2; // Configure DMA for Continuous Ping-Pong mode<br />
DMA0PAD=(int)&ADC1BUF0; <br />
DMA0CNT = 1; // generate dma interrupt every 2 samples <br />
// same as SMPI because only 1 dma buffer per channel <br />
DMA0REQ = 13; // Select ADC1 as DMA Request source<br />
DMA0STA = __builtin_dmaoffset(adc_bufA); <br />
DMA0STB = __builtin_dmaoffset(adc_bufB);<br />
_DMA0IF = 0; // Clear the DMA interrupt flag bit<br />
_DMA0IE = 1; // Set the DMA interrupt enable bit<br />
DMA0CONbits.CHEN=1; // Enable DMA<br />
}<br />
<br />
void _ISR _DMA0Interrupt(void)<br />
{<br />
ADC16Ptr = (which_dma == 0)? adc_bufA : adc_bufB; //Update pointer<br />
adc_data_ready = 1;<br />
which_dma ^= 1; //Next buffer to be used<br />
_DMA0IF = 0; //Clear the DMA0 Interrupt Flag<br />
}<br />
<br />
static void adcAdd(unsigned char ch){<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
TRISB = TRISB | mask;<br />
AD1CSSL = AD1CSSL | mask; <br />
AD1PCFG = ~AD1CSSL;<br />
AD1CON2bits.SMPI++; //take one more sample per interrupt<br />
DMA0CNT++; <br />
}<br />
<br />
static void adcRm(unsigned char ch){<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
AD1PCFG = AD1PCFG | mask;<br />
AD1CSSL = ~AD1PCFG;<br />
AD1CON2bits.SMPI--; //take one less sample per interrupt<br />
DMA0CNT--; <br />
}<br />
<br />
====EEPROM====<br />
<br />
----<br />
*There is no EEPROM in dsPIC33 devices. Please consider to use an external EEPROM using I<sup>2</sup>C communication.<br />
<br />
====Simple PWM====<br />
<br />
----<br />
*No change is required.<br />
<br />
===Memory Map for dsPIC33FJ128GP306===<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 11.1 Memory Location<br />
! Type !! Start Address !! End Address !! Size<br />
|-valign="top"<br />
| Flash || 0x000000 ||0x0157FF || 86K<sup>[1]</sup><br />
|-valign="top"<br />
| +--Flash: Reset Vector || 0x000000 ||0x000003 || 4<br />
|-valign="top"<br />
| +--Flash: Interrupt Vector Table || 0x000004 ||0x0000FF || 252<br />
|-valign="top"<br />
| +--Flash: Alternate Vector Table || 0x000104 ||0x0001FF || 252<br />
|-valign="top"<br />
| +--Flash: User Program || 0x000200 ||0x0157FF || 85.5K<br />
|-valign="top"<br />
| Programming Executive || 0x800000 || 0x800FFF || 4K<sup>[1]</sup><br />
|-valign="top"<br />
| Config Registers || 0xF80000 || 0xF80017 || 24<br />
|-valign="top"<br />
| Device ID (0xE5) || 0xFF0000 || 0xFF0003 || 4<br />
|-<br />
|}<br />
[1] Each address is 16-bit wide. Every two addresses correspond to a 24-bit instruction. Each even address contains 2 valid bytes; each odd address contains 1 valid byte plus 1 phathom byte.<br><br />
<br />
===Custom Linker Script to Maximize Space for Constant Data===<br />
*Constant data declared using keyword '''const''' will be stored in the .const section in the flash memory.<br />
*Normally, during compilation, the linker will assign these data after the program code (.text section).<br />
*Since .const is accessed by auto-psv function, to maximize the space for constant data (32kb), the .const section needs to be aligned at 0x80000 boundary.<br />
*This requires the following change in linker script:<br />
<br />
__CONST_BASE = 0x8000;<br />
<br />
.text __CODE_BASE :<br />
{<br />
*(.reset);<br />
*(.handle);<br />
*(.libc) *(.libm) *(.libdsp); /* keep together in this order */<br />
*(.lib*);<br />
/* *(.text); deleted to maximize space for const data */<br />
} >program<br />
<br />
.const __CONST_BASE :<br />
{<br />
*(.const);<br />
} >program<br />
<br />
*If your program is large, after this change in linker script, function calls may involve large jump in the memory map (>32kB). As a result, you may need to enable the large code and large memory model during compilation. In such case, use the following options in your build path:<br />
-mlarge-code -mlarge-data<br />
*Meanwhile, functions that are defined in the standard C libraries, but are replaced with your own implementations (e.g. I/O stubs: open(), read(), write(), lseek(), ioctl() etc.) may have the following linker error:<br />
/usr/pic30-elf/lib//libc-elf.a(fflush.eo)(.libc+0x3c): In function '.LM11':<br />
: Link Error: relocation truncated to fit: PC RELATIVE BRANCH _write<br />
/usr/pic30-elf/lib//libc-elf.a(fclose.eo)(.libc+0x42): In function '.LM18':<br />
: Link Error: relocation truncated to fit: PC RELATIVE BRANCH _close <br />
*To resolve the problem, you need to place the functions in the .libc section rather than in the .text section, like this:<br />
#define LIBC_CODE_LOC __attribute__ ( (section(".libc")))<br />
<br />
int LIBC_CODE_LOC open(const char *pathname, int flags){ ... }<br />
int LIBC_CODE_LOC close(int fd){ ... }<br />
int LIBC_CODE_LOC write(int fd, void* buf, int count) { ... }<br />
int LIBC_CODE_LOC read(int fd, void* buf, int count) { ... }<br />
int LIBC_CODE_LOC ioctl(int fd, int request, void* argp) { ... }<br />
int LIBC_CODE_LOC lseek(int fd, int offset, int whence) { ... }<br />
<br />
===dsPicBootloader and dsPicProgrammer===<br />
*RTSP for dsPIC33F is different from dsPIC30F.<br />
**Row size changes from 32 instructions (96bytes) to 64 instructions (192 bytes)<br />
**Erase operation changes from 1 row to 8 rows<br />
**No EEPROM<br />
*With regards to the above changes, dsPicBootloader and dsPicProgrammer has been modified. In particular, dsPicProgrammer can be used to program both dsPic30F and dsPic33F devices (Yet, dsPic33F is no longer compatible with Ingenia's programmer). You can easily add your devices to the source code.<br />
<br />
==Downloads==<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 12.1 Related software download links for dsPicBootloader and dsPicProgrammer<br />
! Program<br />
! Site 1<br />
! Site 2<br />
! Remarks<br />
|- valign="top"<br />
| JDK<br />
| [http://java.sun.com/javase/downloads/index.jsp website]<br />
| <br />
| Download latest JDK<br />
|- valign="top"<br />
| RXTX<br />
| [http://users.frii.com/jarvi/rxtx/download.html website]<br />
| <br />
| Download rxtx-2.1-7-bins-r2.zip or later<br />
|- valign="top"<br />
| dsPicBootloader<br />
| [http://chungyan5.no-ip.org/vc click]<br />
| [http://www.opencircuits.com/images/a/a7/DsPicBootloader_1_3_1.zip click (v1.3)]<br />
| Under "dsPicBootloader/", download bl_5011.s or bl_j128gp306.s<br />
|-valign="top"<br />
| dsPicProgrammer<br />
| [http://chungyan5.no-ip.org/vc click]<br />
| [http://www.opencircuits.com/images/9/9e/DsPicProgrammer_1_3_5.zip click (v1.3.5)]<br />
| Under "dsPicProgrammer/", dowload dsPicProgrammer.jar<br><br>Alternatively, if you want to compile yourself or modify the source code, download <br>all source files under "dsPicProgrammer/" '''plus''' RdFileIntelHex.java under <br>"IntelHexPaser/tags/0.02.00/".<br>You should also install RXTX on your local machine as recommended in the readme file.<br />
|- valign="top"<br />
| Ingenia's bootloader<br />
| [http://www.ingenia-cat.com/en/downloads.php website]<br />
| <br />
| Download original ingenia's bootloader<br />
|-<br />
|}<br />
<br />
==ToDo==<br />
*dspic gcc compiler for constant problem<br />
*add chip to stable voltage upon power failure or to detect low voltage, and generate interrupt for dsPic to execute shutdown routine (e.g. save important data to NVM, shutdown ethernet etc.)<br />
*program the bootloader into flash under linux platform</div>Yanhttp://www.opencircuits.com/index.php?title=Basic_Circuit_Building_Blocks&diff=16048Basic Circuit Building Blocks2008-07-29T02:47:15Z<p>Yan: /* Pull Up and Switch */ cct & picture of debouncing</p>
<hr />
<div>These are circuits and parts of circuits that we see over and over again in larger projects. Understanding a complex circuit is much easier if you understand these building blocks. <br />
<br />
Operational amplifier are the basis for many circuit building blocks especially in the range of DC to 1 meg Hz. See [[OpAmp Links]].<br />
<br />
== Page Status.... ==<br />
( [[russ_hensel]] was building this page, but is now distracted so further progress ma;y be up to you. His schematics have been drawn in Eagle and the screen captured. Feel free to add your own circuits, as long as they are basic building blocks, there are lots of other places for project circuits. <br />
Some entries are not complete, if the explanation of the circuit does not match the diagram that is a good tip off. For some reason even some of the uploaded graphics are not showing up, I am working on this as well.<br />
<br><br />
To Do <br />
* Why not put alpha order?<br />
* work on external links<br />
<br />
more circuits that would be good to add<br />
*Constant Current Circuit<br />
*Wheatstone Bridge.<br />
[http://itp.nyu.edu/physcomp/sensors/Schematics/WheatstoneBridge Wheatstone Bridge]<br />
*AC Coupling Capacitor / High Pass Filter<br />
*Battery Lamp and Switch<br />
*Diode Rectifier<br />
*LM35 Temperature Sensor<br />
*555 Timer astable oscillator<br />
*diode for forward drop bias voltage<br />
*row and collumn connection<br />
*charge pump<br />
*transformer<br />
*voltage multiplier<br />
*diode logical or<br />
*RC timer<br />
*diode full wave bridge<br />
*H Bridge<br />
*Simple Oscillator circuits<br />
*Current mirrors<br />
*RF Mixers<br />
*[[Colpitts Oscillator]]<br />
<br />
An H bridge is an electronic circuit that causes current to flow in one direction or the other ( from a singel ended power supply ). Often used for motor control. It is an electronic double pole double throw switch.<br />
[http://code.rancidbacon.com/ElectronicsElectronics] See Section on ''H-Bridge''<br />
<br />
<br />
<br />
<!---------------------------------------------------------------------><br />
<br />
== Current Sense Resistor ( Shunt Resistance ) ==<br />
<br />
A current Sense Resistor is a low value of resistor that is placed in series with some other circuit. We can then measure the voltage across the resistor to compute the current. If the resistor has a low value compared to other components we can ignore the effect on the circuit. We use the word shunt when the voltage is measured by a device that has a fairly low resistance itself. We then have to do a more careful calculation of how the current is shared by the two devices.<br />
<br />
Circuit:<br />
[[Image:shunt.png | Shunt Resistance ]]<br />
<br />
Where<br />
*R shunt resistor used to sense the current ( and divert it from the meter ). Usually much less in value than the internal resistance of the meter.<br />
*METER meter or other device used to measure the voltage across the shunt reistor. Often the resistance of the meter is ignored ( if high ).<br />
*BATTERY a battery or other voltage source.<br />
<br />
Discussion:<br />
<br />
In the old days a sensitive meter, say 50 mv full scale, would be used with a set of shunt, some looking like metal bars, to measure a wide range of currents, up to and exceeding 50 amps.<br />
<br />
More information: <br />
#[http://www.scienceshareware.com/bg-current-monitoring.htm Scienceshareware.com's How A Precision Resistor Is Used to Measure / Calculate Current and Power in an Electrical Circuit.]<br />
#[http://www.maxim-ic.com/appnotes.cfm/appnote_number/746/ High-Side Current-Sense Measurement: Circuits and Principles]<br />
#[http://en.wikipedia.org/wiki/Shunt_(electrical) Shunt (electrical) From Wikipedia, the free encyclopedia]<br />
* Other ways to measure current: [[Motor_driver#current_sense]]<br />
<br />
== Filter Capacitor / Decoupling Capacitor / Low Pass Filter ==<br />
Circuit:<br />
[[Image:filtercap.png | Filter Capacitor ]]<br />
<br />
Where<br />
*D2 is a diode, it lets current pass only in the direction of the arrow.<br />
*R resistor <br />
*Input a source of alternating current ( ocasionally DC in which case the whole circuit serves only to protect against a reverse connection.<br />
C1 the first, main, filter capacitor.<br />
C2 the second filter capicator.<br />
<br />
Discussion:<br />
In this circuit C1 is a classic filter capacitor it charges while the diode conducts, it discharges and supplies current when the diode does not. R and C2 are a second stage filter. With R set to 0, it simply adds to the value of C1. With R in the circit it forms a low pass filter which helps remove the ripple from the power ( at the cost of some voltage drop ). In the old days R would often be a low value inductor which had a similar effect without the voltage drop. A capacitor alone is often put across a circuit component that uses power to supply bursts of current and stop noise from being propigated through the power supply.<br />
<br />
More Information:<br />
<!---------------------------------------------------------------------><br />
<br />
== Op amp Non Inverting Amplifier ==<br />
Circuit:<br />
[[Image:opamp_nia.png | Op amp Non Inverting Amplifier ]]<br />
<br />
Where<br />
*R1 resistor 1 or any other 2 terminal component, capacitor, inductor, diode....<br />
*R2 resistor 2 or any other 2 terminal component.....<br />
OPAMPA Any general purpose op amp, often connected to + and - power supplies<br />
<br />
Discussion:<br />
Gain is = ( R1/R2 ) + 1 <br />
<br />
More Information:<br />
*[OpAmp Links]<br />
<!---------------------------------------------------------------------><br />
<br />
== Op amp Unity Gain Buffer ==<br />
<br />
Use this circuit when you have a signal of high impedance ( can supply only a little current ) that you want to connect to another circuit that draws a significant current ( up to about 10 ma for the typical op amp. ). For example if you wish to measure the out put of a voltage divider with a 0 to 1 ma meter a unity gain buffer might be just what you need. This circuit is also know as a voltage follower.<br />
<br />
The unity gain buffer has an output voltage just the same as the input voltage. The advantage is that the input circuit does not “feel” the output. That is the input acts pretty much like a very large resistor ( many mega ohms or more ) connected to ground, and the output supply's whatever current ( up to about 10 ma ) is necessary to maintain the output voltage. Here is the circuit:<br />
<br />
Circuit:<br />
<br />
[[Image:opamp_ugb.png | Op Amp Unity Gain Buffer ]]<br />
<br />
Where<br />
*INPUT the input signal you wish to buffer<br />
*RIN the input resistor, often 0 ohms.<br />
*OPAMPA Any general purpose op amp, often connected to + and - power supplies<br />
*RFB the feed back resistor <br />
*OUTPUT the output<br />
<br />
Discussion:<br />
The values of RIN and RFB are not very critical and are normally 0 ohms, just a straight connection. The op amp here is a quad or 4 op amp part, we are using just one section of it. Power needs to be supplied to pin 8 and 4 in the usual way for op amps.<br />
<br />
More information: <br />
*[[OpAmp Links]]<br />
*[http://en.wikipedia.org/wiki/Buffer_amplifier Buffer amplifier From Wikipedia, the free encyclopedia]<br />
*[http://www.bcae1.com/opamp.htm Operational Amplifiers]<br />
*[http://www.eecs.tufts.edu/~dsculley/tutorial/opamps/opamps5.html Op-Amp Buffer]<br />
<br />
<!---------------------------------------------------------------------><br />
<br />
== Parallel Circuit ==<br />
In a parallel circuit the current divides and some flows through each component . The key to these circuits is that the voltage is the same in every element of the circuit and the total of the current through each of the components adds up to the total current from the battery. When you use a current meter it is always placed in series with the part of the circuit where you wish to measure the current.<br />
<br />
Circuit:<br />
[[Image:parallel.png | Parallel Circuit ]]<br />
<br />
Where<br />
*R1 resistor 1 or any other 2 terminal component, capacitor, inductor, diode....<br />
*R2 resistor 2 or any other 2 terminal component.....<br />
*BATTERY a battery or other voltage source<br />
<br />
Discussion:<br />
<br />
I you have a lot of components that use the same voltage put them in parallel. This is how most lights in a house are wired. Each individual light can be turned on and off without changing the current or voltage in the other lights. With a bit of math you can show that the two resistors act like one resistor of value R = R1 + R2 /( R1 * R2 ). When you need a resistor of a different value than you have you can sometimes “make it up” using a parallel connection of resistors you do have. Two identical resistors in parallel are equivalent to one of half the resistance. A parallel circuit can have more than 2 resistors, there can be 3, 4, ... You can find out more about parallel circuits in the references. This circuit should be contrasted with the Series Circuit. Parallel circuits can also be used with other components, the equations vary, for capicators the capacitances add in a parallel circuit.<br />
<br />
More information: <br />
* [http://en.wikipedia.org/wiki/Parallel_circuit Series and parallel circuits From Wikipedia, the free encyclopedia]<br />
<!---------------------------------------------------------------------><br />
<br />
== Pull Up and Switch ==<br />
<br />
Use this circuit when you want to feed a user input to a digital circuit, for example a PIC input pin.<br />
<br />
A pull up is a fairly high value resistor (say 1 to 100 K ohms) that is connected to the positive side of the power supply. This makes the other end of the resistor the same voltage as the power supply (as long as it is connected to a high impedance). The other end of the resistor is connected to a switch that is then connected to ground. When the switch is connected current flow through the resistor drops the entire power supply voltage and the input voltage for the circuit is now 0 (sometimes called active low, since when the switch is active the output is low). Pull up is sometimes used without the switch to keep a signal high all the time.<br />
<br />
Circuit:<br />
<br />
[[Image:pus.png | Pull Up and Switch ]]<br />
<br />
Where<br />
*PUSH_BUTTON_SWITCH is a push button switch<br />
*R_PULLUP is the pull up resistor <br />
*VPLUS_VDD is the power supply voltage<br />
<br />
More information: <br />
[http://www.seattlerobotics.org/encoder/mar97/basics.html Very Basic Circuits]<br />
<br />
<br />
Debouncing Discussion:<br />
<br />
We have two groups of solution: Hardware Debouncing Circuit and Software Debouncing Driver<br />
<br />
<br />
Hardware Debouncing Circuit:<br />
<br />
[[Image:Pus_debouncing.PNG | Pull Up and Switch with debouncing ]]<br />
with [http://chungyan5.no-ip.org/open_data/electronic_computer/ui/key_with_debouncing geda circuit], and [http://chungyan5.no-ip.org/open_data/electronic_computer/eda/geda/libs symbols]<br />
*Advantage - Do not occupy the CPU processing power for debouncing, lets CPU to handle more other application task(s)<br />
*Disadvantage - we need to implement the above hardware circuit inside the project<br />
<br />
<br />
Software Debouncing Driver:<br />
*Advantage - Saving cost & space for nothing debouncing circuit<br />
*Disadvantage - Utilize CPU processing power for debouncing, less time for CPU to handle other application process<br />
<br />
<br />
===ToDo===<br />
*Software Debouncing Driver<br />
**compile time parameters:<br />
***time delay between each sample<br />
***no. of sample - until all samples <br />
**different type of switches, may be have different above compile time parameters<br />
**API to OS or GUI<br />
<br />
<br />
<!---------------------------------------------------------------------><br />
<br />
== Pull Down and Switch ==<br />
Circuit:<br />
[[Image:pds.png | Pull Down and Switch ]]<br />
<br />
Where<br />
*R_PULLDOWN resistor which normally keeps the output low ( ground ).<br />
*PUSH_BUTTON_SWITCH switch to make the output high<br />
*VPLUS_VDD a battery or other voltage source<br />
<br />
Discussion:<br />
Just a variation on the Pull Up and Switch.<br />
<!---------------------------------------------------------------------><br />
<br />
== Series Circuit ==<br />
<br />
In a series circuit the current first flows through one component then another and so on. The key to these circuits is that the current is the same in every element of the circuit and the total of the voltage across each of the components adds up to the voltage of the battery. A current meter is always in series with the part of the circuit whose current is being measured.<br />
<br />
Circuit:<br />
[[Image:series.png | Series Circuit ]]<br />
<br />
Where<br />
*R1 resistor 1 or any other 2 terminal component, capacitor, inductor, diode....<br />
*R2 resistor 2 or any other 2 terminal component.....<br />
*BAT a battery or other voltage source<br />
<br />
I you have a lot of components that use the same current put them in series. This is often how LEDs are connected to higher voltages; this also eliminates the need for a current limiting resistor on each LED. With a bit of math you can show that the two resistors act like one resistor of value R = R1 + R2 . When you need a resistor of a different value than you have you can sometimes “make it up” using a series connection of resistors you do have. Two identical resistors in series are equivalent to one of double the resistance. A series circuit can have more than 2 resistors, there can be 3, 4, ... You can find out more about series circuits in the references. This circuit should be contrasted with the Parallel Circuit. A voltage divider is an example of a series circuit.<br />
<br />
More information: <br />
* [http://en.wikipedia.org/wiki/Parallel_circuit Series and parallel circuits From Wikipedia, the free encyclopedia]<br />
<br />
<!---------------------------------------------------------------------><br />
<br />
== Three Terminal Regulator ==<br />
<br />
Use when you need a regulated voltage and or short circuit protection.<br />
<br />
Most circuits run better if the primary power source is a constant fixed voltage. A battery is only a poor approximation to this. Taking a battery or other voltage source ( like a wall wart plug in transformer ) and running it through a voltage regulator transforms it into a good fixed source of voltage. It also generally adds current limiting as short circuit protection. The 7805 is a very common 5 volt regulator. <br />
<br />
Circuit:<br />
[[Image:ttr.png | Three Terminal Regulator ]]<br />
<br />
Discussion:<br />
<br />
The circuit above is very basic. Practical circuits normally include filter capacitors on both the input and the output. Most regulators protect against both over temperature and over current. Regulators come in various voltages both positive and negative. They also vary in maximum current output. There are also adjustable regulators, ways of using regular regulators as adjustable ones, and ways of boosting the current output. The spec sheets often describe how to do these things. Voltage regulators “use up” a couple of volts of the input voltage, low drop out regulators have use less, cost more. It is a good idea to check the specification for any regulator you are going to use. The LM78xx ( positive ) and LM79xx ( negative ) are quite common.<br />
<br />
More information: <br />
*[[Basic Voltage Regulators]] <br />
*[http://en.wikipedia.org/wiki/7805 7805 From Wikipedia, the free encyclopedia]<br />
*[http://www.tkk.fi/Misc/Electronics/circuits/psu_5v.html Simple 5V power supply for digital circuits]<br />
<br />
== Diode Snubber ==<br />
<br />
Use when an inductive element in a circuit is likely to generate an undesired voltage when the current is suddenly stopped.<br />
<br />
The diode is connected in reverse from the normal voltage across the inductor, when the voltage is removed the collapsing field can continue to drive current through the diode without generating a high voltage.<br />
<br />
Circuit:<br />
[[Image:diodesnubber.png | Diode snubbber ]]<br />
<br />
Discussion:<br />
<br />
In the circuit shown, the inductor is the relay coil, the transistor is just one way, and a common one, that might suddenly shut down the voltage/current to the inductor. This circuit is a common one for controlling a large voltage/current with a very small one. Other inductors that might use a snubber are transformers, solenoids, dc motors, and of course straight ahead inductors.<br />
<br />
More information: <br />
*[http://en.wikipedia.org/wiki/snubber "snubber" from Wikipedia, the free encyclopedia]<br />
*[http://en.wikipedia.org/wiki/flyback_diode "flyback diode" from Wikipedia, the free encyclopedia]<br />
<br />
== Transistor Low Side Switch ==<br />
<br />
Use this circuit when you wish to turn a load on and off with both a low voltage and a low current. Note that neither side of the load is grounded.<br />
<br />
A low side switch is one which switches a circuit on and off at the ground or low side of the circuit. The advantage of a low side switch is that when using a transistor as the switch the voltage to drive the transistor is itself a low voltage. It is often the easy way to drive LEDS, motors, and other high current devices from such low power devices as PIC output ports. Low side switches are popular and there are many integrated circuits for them as well as this circuit.<br />
<br />
Circuit:<br />
<br />
[[Image:Tran_lss.jpg | Transistor Low Side Switch ]]<br />
<br />
Where<br />
*LED is a low power LED<br />
*R_LED is a current limiting resistor for the LED<br />
*Q is a bipolar transistor <br />
*R_1 is a current limiting resistor transistor base current<br />
*VPLUS_VDD is the power supply for the LED<br />
<br />
<br />
Discussion:<br />
The voltage at the collector of the circuit should fall to a fraction of a volt when the input is high. To acomplish this:<br />
<br />
*Compute the value of R_LED using ohms law and the specifications for the LED.<br />
*Compute the current through the LED.<br />
*The transistor must supply the current, it should be equal approxtely to the input voltage divided by R1 times the beta of the transistor.<br />
<br />
An example calculation would be nice, and will appear later.<br />
<br />
This circuit is sometimes called "grounded-emitter configuration".<br />
<br />
More Information:<br />
*[http://en.wikipedia.org/wiki/Transistor#Switches Transistor From Wikipedia, the free encyclopedia]<br />
<br />
== Transistor High Side Switch ==<br />
<br />
Use this circuit when you wish to turn a load on and off with a voltage at a low current. Note that low side of the load is grounded. The voltage to turn on the switch is equal to the supply voltage ( or perhaps just a bit larger )<br />
<br />
A high side switch is one which switches a circuit on and off at the supply voltage or high side of the circuit. The advantage of a high side switch is that the load is grounded on one side. Compared to the low side switch it needs a higher voltage to drive it, but it also eliminates one resistor of that circuit. It the voltage to drive it is available it may be the circuit of choice. It is often the easy way to drive leds motors and other high current devices from such low power devices as PIC output ports. <br />
<br />
Circuit:<br />
<br />
[[Image:tran_hss.png | Transistor High Side Switch ]]<br />
<br />
Where<br />
*LED is a low power LED<br />
*R_LED is a current limiting resistor for the LED<br />
*Q is a bipolar transistor <br />
*VPLUS_VDD is the power supply for the LED<br />
<br />
The voltage at the collector of the circuit should fall to a fraction of a volt when the input is high. To compute the values in the circuit:<br />
<br />
*Compute the value of R_LED using ohms law and the specifications for the LED.<br />
*The current to drive the circuit is approximately the current to drive the load divided by the beta of the transistor.<br />
<br />
<br />
No resistor is needed into the base of the transistor because as the load draws current the voltage at the base will rise and limit the base current. The input voltage should be about equal to VPLUS_VDD, high compared to that needed for the low side switch.<br />
<br />
== Transistor Emitter Follower ==<br />
<br />
Use this circuit when you have a signal of high impedance ( can supply only a little current ) that you want to connect to another circuit that draws a significant current. The circuit has no voltage gain, but because of the current gain it has a lot of power gain. It is frequently used in the final stage of an amplifier. <br />
<br />
This circuit is a variation of the transistor high side switch. The difference is that we typically drive this circuit in a linear way ( all of the voltages between 0 and the supply voltage ) to make it a linear amplifier.<br />
<br />
The emitter follower is also called a common collector circuit. The Emitter Follower is basically a high side switch, but when we call it an emitter follower we normally think of it as a linear ( analog ) amplifier, rather than as a switch.<br />
<br />
Circuit:<br />
<br />
[[Image:tef.png | Transistor Emitter Follower ]]<br />
<br />
Where<br />
*R_LOAD represents the resistance of the load<br />
*Q is a npn bipolar transistor <br />
*VPLUS_VDD is the power supply for the LED<br />
<br />
The current to drive the circuit is approximately the current to drive the load divided by the beta of the transistor. Use a Darlington connected transistor for a very high beta.<br />
<br />
No resistor is needed into the base of the transistor because as the load draws current the voltage at the base will rise and limit the base current. <br />
<br />
This circuit will only amplify positive voltages, using a pnp transistor you can amplify only negative voltages. Combine the two ( see push pull amplifier ) you can amplify both positive and negative voltages.<br />
<br />
<br />
<br />
Variation of the circuit include: <br />
<br />
*Use of coupling capacitors to amplify ac signals.<br />
*Various other components to bias the transistor.<br />
*Use an op amp buffer with voltage gain at the input, then the emitter follower for high current. In this way a few Milli volts with current on the order of pico amps can drive an output of several volts at an ampere or more. <br />
<br />
More information: <br />
<br />
*[http://www.mines.edu/Academic/courses/physics/phgn217/lab4/lect7/sld013.htm Emitter Follower]<br />
<br />
*[http://en.wikipedia.org/wiki/Common_collector Common collector From Wikipedia, the free encyclopedia]<br />
<br />
== Voltage Divider ==<br />
Voltage Divider<br />
<br />
We use a voltage divider when we have a voltage that is too big and we just want a fraction ( like 1/3 or .33 ) of it. It is like an amplifier with a gain of less than 1. We use two resistors, the output is always a constant fraction of the input voltage.<br />
<br />
Sometimes we use a potentiometer as a voltage divider. This makes the ratio of output to input adjustable. This is how we make a gain control or volume control.<br />
<br />
Circuit:<br />
[[Image:vdivide.png | Voltage Divider ]]<br />
<br />
Where<br />
*R1 resistor 1<br />
*R2 resistor 2<br />
*POT a potentiometer<br />
<br />
The ratio of input to output is: output/input = R2/( R1 + R2 ).<br />
<br />
Discussion<br />
<br />
The equation assumes that the input source is low impedance and the output is high impedance, if this is not true consider using a buffer on the input or the output ( Op Amp Unity Gain Buffer or Transistor Emitter Follower ) For audio applications a so called “log taper” pot may be used as it better matches the way in which we hear. If you want a calibrated control you may use a precision “10 turn precision” pot.<br />
<br />
More information: <br />
*[http://www.seattlerobotics.org/encoder/mar97/basics.html Very Basic Circuits]<br />
*[http://itp.nyu.edu/physcomp/sensors/Schematics/VoltageDivider Voltage Divider]<br />
<br />
== RC Filter ==<br />
<br />
The most basic filters are the RC-High Pass and RC-Low Pass filters. The high pass filter removes DC and low frequencies and the low pass removes high frequencies. <br />
<br />
<br />
'''High Pass''' [[Image:rchighpass.png | RC High Pass Filter]]<br />
'''Low Pass''' [[Image:rclowpass.png | RC Low Pass Filter]]<br />
<br />
Both circuits have the same 3dB frequency or the frequency at which the power of the signal is aproximately halved.<br />
<br />
<math><br />
f_\mathrm{c} = {1 \over 2 \pi \tau } = {1 \over 2 \pi R C}<br />
</math><br />
<br />
The way to remember the two circuits is to think about how the capacitor acts at various signal frequencies. At high frequencies capacitors act like wires. At low frequencies capacitors act like disconnections.<br />
<br />
An important use of low pass filters is for the anti-aliasing circuity on the input of an A/D converter or the output of a D/A converter. An important use of a high pass filter is to remove the DC offset of a signal. For example, it's possible to use a power supply that is +5 to GND to generate a sin from a D/A converter and use a high pass filter to change the sin to a +2.5 to -2.5 signal at the output.<br />
<br />
More information:<br />
*[http://en.wikipedia.org/wiki/Low-pass_filter Low Pass Filter]<br />
*[http://en.wikipedia.org/wiki/High-pass_filter High Pass Filter]<br />
<br />
== Light Emitting Diode ( with current limiting resistor ) ==<br />
<br />
Use this circuit to light low power LEDs<br />
<br />
A light emitting diode can be very sensitive to small voltage changes, just a bit too much voltage and the LED will draw too much current and “burn out”. Thus it is often used with a resistor in series. If we have a 5 volt source of voltage and an LED that is specified for 2.5 volts at 10 ma, then the resistor must have ( 5 – 2.5 ) volts = 2.5 volts and 10 ma. Using ohms law 2.5/10 x 10 ee-3 = 250 ohms.<br />
<br />
A transistor low or high side switch can be used with the resistor if your input cannot supply enough current for the LED.<br />
<br />
Circuit:<br />
[[Image:ledres.jpg | LED and current limiting resistor ]]<br />
<br />
Where<br />
*LED the LED<br />
*R_LED the current limiting resistor<br />
*INPUT voltage source for lighting the LED<br />
<br />
More information: <br />
*[http://www.seattlerobotics.org/encoder/mar97/basics.html Very Basic Circuits ] <br />
*[http://www.iguanalabs.com/1stled.htm Learning About Transistors and LEDs ]<br />
<br />
== Transistor -- Push Pull Circuit ==<br />
<br />
Use when you need current gain and need both positive and negative output.<br />
<br />
A modification of the “transistor emitter follower” that can give both positive and negative outputs. Based on two transistors one npn the other pnp: one pushes the other pulls.<br />
<br />
Circuit:<br />
[[Image:pptrans.png | Push Pull Transistor Circuit]]<br />
<br />
Where<br />
*Q1 transistor 1 need not be a TIP41C but does need to be NPN<br />
*Q2 transistor 2 need not be a TIP42C but does need to be PNP<br />
*R_LOAD represents the load, here it is in the emitter, it could also be placed in the collector circuit<br />
*VPLUS_VDD Power supply voltage, positive.<br />
*VMINUS Power supply voltage, negative.<br />
<br />
Discussion:<br />
Often there are other components for transistor bias or other purposes. The circuit here is really basic. The common transistors used are so called complementary pairs, similar characteristics but one npn and the other pnp. Note that we need both positive and negative power supplies. You can also put the push pull circuit inside the feedback loop of an op amp to get a high current op amplifier. Push pull amplifies can also be made with other types of transistors, tubes, or other components.<br />
<br />
More information: <br />
*[http://www.ecircuitcenter.com/Circuits/pushpull/pushpull.htm Push-Pull Output Stage]<br />
*[http://www.allaboutcircuits.com/vol_6/chpt_6/10.html Class B audio amplifier]<br />
*[http://en.wikipedia.org/wiki/Electronic_amplifier Electronic amplifier From Wikipedia, the free encyclopedia (search on Class B and AB )]<br />
<br />
== Transistors -- Darlington connected ==<br />
<br />
Use a Darlington transistor connection when you want really high current gain. Gain of 1000 is easily in reach. That is 1 ma to 1 amp <br />
This is a useful connection of 2 transistors that together form a transistor of much larger gain. You can also buy Darlington transistors all packaged in a single case with just 3 connections exposed to the outside.<br />
<br />
Circuit:<br />
[[Image:dtrans.png | Darlington Transistor Connection ]]<br />
<br />
Where<br />
*Q1 transistor 1 need not be a 2N3565 but does need to be NPN<br />
*Q2 transistor 2 need not be a 2N3565 but does need to be NPN<br />
*R_LOAD represents the load, here it is in the emitter, it could also be placed in the collector circuit<br />
*VPLUS_VDD Power supply voltage, positive.<br />
<br />
Discussion:<br />
<br />
Often Q1 is a high gain small signal transistor and Q2 a lower gain power transistor. You can use PNP transistors by using a negative power supply. Use a ULN2803 ( or similar chips ) to get 8 darlingtons in one package, useful as low side switches and in conjunction with microcontrollers.<br />
<br />
More information: <br />
* http://en.wikipedia.org/wiki/Darlington_transistor Darlington transistor From Wikipedia, the free encyclopedia]<br />
*[http://www.kpsec.freeuk.com/trancirc.htm Transistor Circuits ( search on Darlington )]<br />
*[http://www.ibiblio.org/kuphaldt/electricCircuits/Semi/SEMI_4.html Lessons In Electric Circuits -- Volume III Chapter 4 BIPOLAR JUNCTION TRANSISTORS Darlington pair ( search on Darlington )]<br />
<br />
== Schmitt Trigger ==<br />
Circuit:<br />
[[Image:opamp_st.png | Schmitt Trigger ]]<br />
<br />
Where<br />
*RIN input resistor -- when this inputs more current than the positive feedback resistor the output switches to the voltage at the input, else it stays at the output voltage it has already reached. Typically lower in value than RFB.<br />
*RFB positive feedback resistor the output voltage is feed back to the input and keeps the output at its current voltage.<br />
<br />
<br />
Discussion:<br />
<br />
The circuit is used to switch between two states even in the presence of noise. This is an somewhat unusual op amp circuit as it uses positive not negative feedback. See the references for a better explanation and variations on the circuit.<br />
Schmidt Triggers are also available as integrated circuits which require no external components.<br />
<br />
More Information:<br />
*[[OpAmp Links]]</div>Yanhttp://www.opencircuits.com/index.php?title=File:Pus_debouncing.PNG&diff=16047File:Pus debouncing.PNG2008-07-29T02:09:45Z<p>Yan: pullup switch with debouncing</p>
<hr />
<div>pullup switch with debouncing</div>Yanhttp://www.opencircuits.com/index.php?title=Basic_Circuit_Building_Blocks&diff=16045Basic Circuit Building Blocks2008-07-28T10:04:12Z<p>Yan: /* Pull Up and Switch */ debouncing</p>
<hr />
<div>These are circuits and parts of circuits that we see over and over again in larger projects. Understanding a complex circuit is much easier if you understand these building blocks. <br />
<br />
Operational amplifier are the basis for many circuit building blocks especially in the range of DC to 1 meg Hz. See [[OpAmp Links]].<br />
<br />
== Page Status.... ==<br />
( [[russ_hensel]] was building this page, but is now distracted so further progress ma;y be up to you. His schematics have been drawn in Eagle and the screen captured. Feel free to add your own circuits, as long as they are basic building blocks, there are lots of other places for project circuits. <br />
Some entries are not complete, if the explanation of the circuit does not match the diagram that is a good tip off. For some reason even some of the uploaded graphics are not showing up, I am working on this as well.<br />
<br><br />
To Do <br />
* Why not put alpha order?<br />
* work on external links<br />
<br />
more circuits that would be good to add<br />
*Constant Current Circuit<br />
*Wheatstone Bridge.<br />
[http://itp.nyu.edu/physcomp/sensors/Schematics/WheatstoneBridge Wheatstone Bridge]<br />
*AC Coupling Capacitor / High Pass Filter<br />
*Battery Lamp and Switch<br />
*Diode Rectifier<br />
*LM35 Temperature Sensor<br />
*555 Timer astable oscillator<br />
*diode for forward drop bias voltage<br />
*row and collumn connection<br />
*charge pump<br />
*transformer<br />
*voltage multiplier<br />
*diode logical or<br />
*RC timer<br />
*diode full wave bridge<br />
*H Bridge<br />
*Simple Oscillator circuits<br />
*Current mirrors<br />
*RF Mixers<br />
*[[Colpitts Oscillator]]<br />
<br />
An H bridge is an electronic circuit that causes current to flow in one direction or the other ( from a singel ended power supply ). Often used for motor control. It is an electronic double pole double throw switch.<br />
[http://code.rancidbacon.com/ElectronicsElectronics] See Section on ''H-Bridge''<br />
<br />
<br />
<br />
<!---------------------------------------------------------------------><br />
<br />
== Current Sense Resistor ( Shunt Resistance ) ==<br />
<br />
A current Sense Resistor is a low value of resistor that is placed in series with some other circuit. We can then measure the voltage across the resistor to compute the current. If the resistor has a low value compared to other components we can ignore the effect on the circuit. We use the word shunt when the voltage is measured by a device that has a fairly low resistance itself. We then have to do a more careful calculation of how the current is shared by the two devices.<br />
<br />
Circuit:<br />
[[Image:shunt.png | Shunt Resistance ]]<br />
<br />
Where<br />
*R shunt resistor used to sense the current ( and divert it from the meter ). Usually much less in value than the internal resistance of the meter.<br />
*METER meter or other device used to measure the voltage across the shunt reistor. Often the resistance of the meter is ignored ( if high ).<br />
*BATTERY a battery or other voltage source.<br />
<br />
Discussion:<br />
<br />
In the old days a sensitive meter, say 50 mv full scale, would be used with a set of shunt, some looking like metal bars, to measure a wide range of currents, up to and exceeding 50 amps.<br />
<br />
More information: <br />
#[http://www.scienceshareware.com/bg-current-monitoring.htm Scienceshareware.com's How A Precision Resistor Is Used to Measure / Calculate Current and Power in an Electrical Circuit.]<br />
#[http://www.maxim-ic.com/appnotes.cfm/appnote_number/746/ High-Side Current-Sense Measurement: Circuits and Principles]<br />
#[http://en.wikipedia.org/wiki/Shunt_(electrical) Shunt (electrical) From Wikipedia, the free encyclopedia]<br />
* Other ways to measure current: [[Motor_driver#current_sense]]<br />
<br />
== Filter Capacitor / Decoupling Capacitor / Low Pass Filter ==<br />
Circuit:<br />
[[Image:filtercap.png | Filter Capacitor ]]<br />
<br />
Where<br />
*D2 is a diode, it lets current pass only in the direction of the arrow.<br />
*R resistor <br />
*Input a source of alternating current ( ocasionally DC in which case the whole circuit serves only to protect against a reverse connection.<br />
C1 the first, main, filter capacitor.<br />
C2 the second filter capicator.<br />
<br />
Discussion:<br />
In this circuit C1 is a classic filter capacitor it charges while the diode conducts, it discharges and supplies current when the diode does not. R and C2 are a second stage filter. With R set to 0, it simply adds to the value of C1. With R in the circit it forms a low pass filter which helps remove the ripple from the power ( at the cost of some voltage drop ). In the old days R would often be a low value inductor which had a similar effect without the voltage drop. A capacitor alone is often put across a circuit component that uses power to supply bursts of current and stop noise from being propigated through the power supply.<br />
<br />
More Information:<br />
<!---------------------------------------------------------------------><br />
<br />
== Op amp Non Inverting Amplifier ==<br />
Circuit:<br />
[[Image:opamp_nia.png | Op amp Non Inverting Amplifier ]]<br />
<br />
Where<br />
*R1 resistor 1 or any other 2 terminal component, capacitor, inductor, diode....<br />
*R2 resistor 2 or any other 2 terminal component.....<br />
OPAMPA Any general purpose op amp, often connected to + and - power supplies<br />
<br />
Discussion:<br />
Gain is = ( R1/R2 ) + 1 <br />
<br />
More Information:<br />
*[OpAmp Links]<br />
<!---------------------------------------------------------------------><br />
<br />
== Op amp Unity Gain Buffer ==<br />
<br />
Use this circuit when you have a signal of high impedance ( can supply only a little current ) that you want to connect to another circuit that draws a significant current ( up to about 10 ma for the typical op amp. ). For example if you wish to measure the out put of a voltage divider with a 0 to 1 ma meter a unity gain buffer might be just what you need. This circuit is also know as a voltage follower.<br />
<br />
The unity gain buffer has an output voltage just the same as the input voltage. The advantage is that the input circuit does not “feel” the output. That is the input acts pretty much like a very large resistor ( many mega ohms or more ) connected to ground, and the output supply's whatever current ( up to about 10 ma ) is necessary to maintain the output voltage. Here is the circuit:<br />
<br />
Circuit:<br />
<br />
[[Image:opamp_ugb.png | Op Amp Unity Gain Buffer ]]<br />
<br />
Where<br />
*INPUT the input signal you wish to buffer<br />
*RIN the input resistor, often 0 ohms.<br />
*OPAMPA Any general purpose op amp, often connected to + and - power supplies<br />
*RFB the feed back resistor <br />
*OUTPUT the output<br />
<br />
Discussion:<br />
The values of RIN and RFB are not very critical and are normally 0 ohms, just a straight connection. The op amp here is a quad or 4 op amp part, we are using just one section of it. Power needs to be supplied to pin 8 and 4 in the usual way for op amps.<br />
<br />
More information: <br />
*[[OpAmp Links]]<br />
*[http://en.wikipedia.org/wiki/Buffer_amplifier Buffer amplifier From Wikipedia, the free encyclopedia]<br />
*[http://www.bcae1.com/opamp.htm Operational Amplifiers]<br />
*[http://www.eecs.tufts.edu/~dsculley/tutorial/opamps/opamps5.html Op-Amp Buffer]<br />
<br />
<!---------------------------------------------------------------------><br />
<br />
== Parallel Circuit ==<br />
In a parallel circuit the current divides and some flows through each component . The key to these circuits is that the voltage is the same in every element of the circuit and the total of the current through each of the components adds up to the total current from the battery. When you use a current meter it is always placed in series with the part of the circuit where you wish to measure the current.<br />
<br />
Circuit:<br />
[[Image:parallel.png | Parallel Circuit ]]<br />
<br />
Where<br />
*R1 resistor 1 or any other 2 terminal component, capacitor, inductor, diode....<br />
*R2 resistor 2 or any other 2 terminal component.....<br />
*BATTERY a battery or other voltage source<br />
<br />
Discussion:<br />
<br />
I you have a lot of components that use the same voltage put them in parallel. This is how most lights in a house are wired. Each individual light can be turned on and off without changing the current or voltage in the other lights. With a bit of math you can show that the two resistors act like one resistor of value R = R1 + R2 /( R1 * R2 ). When you need a resistor of a different value than you have you can sometimes “make it up” using a parallel connection of resistors you do have. Two identical resistors in parallel are equivalent to one of half the resistance. A parallel circuit can have more than 2 resistors, there can be 3, 4, ... You can find out more about parallel circuits in the references. This circuit should be contrasted with the Series Circuit. Parallel circuits can also be used with other components, the equations vary, for capicators the capacitances add in a parallel circuit.<br />
<br />
More information: <br />
* [http://en.wikipedia.org/wiki/Parallel_circuit Series and parallel circuits From Wikipedia, the free encyclopedia]<br />
<!---------------------------------------------------------------------><br />
<br />
== Pull Up and Switch ==<br />
<br />
Use this circuit when you want to feed a user input to a digital circuit, for example a PIC input pin.<br />
<br />
A pull up is a fairly high value resistor (say 1 to 100 K ohms) that is connected to the positive side of the power supply. This makes the other end of the resistor the same voltage as the power supply (as long as it is connected to a high impedance). The other end of the resistor is connected to a switch that is then connected to ground. When the switch is connected current flow through the resistor drops the entire power supply voltage and the input voltage for the circuit is now 0 (sometimes called active low, since when the switch is active the output is low). Pull up is sometimes used without the switch to keep a signal high all the time.<br />
<br />
Circuit:<br />
<br />
[[Image:pus.png | Pull Up and Switch ]]<br />
<br />
Where<br />
*PUSH_BUTTON_SWITCH is a push button switch<br />
*R_PULLUP is the pull up resistor <br />
*VPLUS_VDD is the power supply voltage<br />
<br />
More information: <br />
[http://www.seattlerobotics.org/encoder/mar97/basics.html Very Basic Circuits]<br />
<br />
<br />
Debouncing Discussion:<br />
<br />
We have two groups of solution: Hardware Debouncing Circuit and Software Debouncing Driver<br />
<br />
<br />
Hardware Debouncing Circuit:<br />
<br />
[[Image:pus.png | Pull Up and Switch ]]<br />
*Advantage - Do not occupy the CPU processing power for debouncing, lets CPU to handle more other application task(s)<br />
*Disadvantage - we need to implement the above hardware circuit inside the project<br />
<br />
<br />
Software Debouncing Driver:<br />
*Advantage - Saving cost & space for nothing debouncing circuit<br />
*Disadvantage - Utilize CPU processing power for debouncing, less time for CPU to handle other application process<br />
<br />
<br />
===ToDo===<br />
*Software Debouncing Driver<br />
**compile time parameters:<br />
***time delay between each sample<br />
***no. of sample - until all samples <br />
**different type of switches, may be have different above compile time parameters<br />
**API to OS or GUI<br />
<br />
<br />
<!---------------------------------------------------------------------><br />
<br />
== Pull Down and Switch ==<br />
Circuit:<br />
[[Image:pds.png | Pull Down and Switch ]]<br />
<br />
Where<br />
*R_PULLDOWN resistor which normally keeps the output low ( ground ).<br />
*PUSH_BUTTON_SWITCH switch to make the output high<br />
*VPLUS_VDD a battery or other voltage source<br />
<br />
Discussion:<br />
Just a variation on the Pull Up and Switch.<br />
<!---------------------------------------------------------------------><br />
<br />
== Series Circuit ==<br />
<br />
In a series circuit the current first flows through one component then another and so on. The key to these circuits is that the current is the same in every element of the circuit and the total of the voltage across each of the components adds up to the voltage of the battery. A current meter is always in series with the part of the circuit whose current is being measured.<br />
<br />
Circuit:<br />
[[Image:series.png | Series Circuit ]]<br />
<br />
Where<br />
*R1 resistor 1 or any other 2 terminal component, capacitor, inductor, diode....<br />
*R2 resistor 2 or any other 2 terminal component.....<br />
*BAT a battery or other voltage source<br />
<br />
I you have a lot of components that use the same current put them in series. This is often how LEDs are connected to higher voltages; this also eliminates the need for a current limiting resistor on each LED. With a bit of math you can show that the two resistors act like one resistor of value R = R1 + R2 . When you need a resistor of a different value than you have you can sometimes “make it up” using a series connection of resistors you do have. Two identical resistors in series are equivalent to one of double the resistance. A series circuit can have more than 2 resistors, there can be 3, 4, ... You can find out more about series circuits in the references. This circuit should be contrasted with the Parallel Circuit. A voltage divider is an example of a series circuit.<br />
<br />
More information: <br />
* [http://en.wikipedia.org/wiki/Parallel_circuit Series and parallel circuits From Wikipedia, the free encyclopedia]<br />
<br />
<!---------------------------------------------------------------------><br />
<br />
== Three Terminal Regulator ==<br />
<br />
Use when you need a regulated voltage and or short circuit protection.<br />
<br />
Most circuits run better if the primary power source is a constant fixed voltage. A battery is only a poor approximation to this. Taking a battery or other voltage source ( like a wall wart plug in transformer ) and running it through a voltage regulator transforms it into a good fixed source of voltage. It also generally adds current limiting as short circuit protection. The 7805 is a very common 5 volt regulator. <br />
<br />
Circuit:<br />
[[Image:ttr.png | Three Terminal Regulator ]]<br />
<br />
Discussion:<br />
<br />
The circuit above is very basic. Practical circuits normally include filter capacitors on both the input and the output. Most regulators protect against both over temperature and over current. Regulators come in various voltages both positive and negative. They also vary in maximum current output. There are also adjustable regulators, ways of using regular regulators as adjustable ones, and ways of boosting the current output. The spec sheets often describe how to do these things. Voltage regulators “use up” a couple of volts of the input voltage, low drop out regulators have use less, cost more. It is a good idea to check the specification for any regulator you are going to use. The LM78xx ( positive ) and LM79xx ( negative ) are quite common.<br />
<br />
More information: <br />
*[[Basic Voltage Regulators]] <br />
*[http://en.wikipedia.org/wiki/7805 7805 From Wikipedia, the free encyclopedia]<br />
*[http://www.tkk.fi/Misc/Electronics/circuits/psu_5v.html Simple 5V power supply for digital circuits]<br />
<br />
== Diode Snubber ==<br />
<br />
Use when an inductive element in a circuit is likely to generate an undesired voltage when the current is suddenly stopped.<br />
<br />
The diode is connected in reverse from the normal voltage across the inductor, when the voltage is removed the collapsing field can continue to drive current through the diode without generating a high voltage.<br />
<br />
Circuit:<br />
[[Image:diodesnubber.png | Diode snubbber ]]<br />
<br />
Discussion:<br />
<br />
In the circuit shown, the inductor is the relay coil, the transistor is just one way, and a common one, that might suddenly shut down the voltage/current to the inductor. This circuit is a common one for controlling a large voltage/current with a very small one. Other inductors that might use a snubber are transformers, solenoids, dc motors, and of course straight ahead inductors.<br />
<br />
More information: <br />
*[http://en.wikipedia.org/wiki/snubber "snubber" from Wikipedia, the free encyclopedia]<br />
*[http://en.wikipedia.org/wiki/flyback_diode "flyback diode" from Wikipedia, the free encyclopedia]<br />
<br />
== Transistor Low Side Switch ==<br />
<br />
Use this circuit when you wish to turn a load on and off with both a low voltage and a low current. Note that neither side of the load is grounded.<br />
<br />
A low side switch is one which switches a circuit on and off at the ground or low side of the circuit. The advantage of a low side switch is that when using a transistor as the switch the voltage to drive the transistor is itself a low voltage. It is often the easy way to drive LEDS, motors, and other high current devices from such low power devices as PIC output ports. Low side switches are popular and there are many integrated circuits for them as well as this circuit.<br />
<br />
Circuit:<br />
<br />
[[Image:Tran_lss.jpg | Transistor Low Side Switch ]]<br />
<br />
Where<br />
*LED is a low power LED<br />
*R_LED is a current limiting resistor for the LED<br />
*Q is a bipolar transistor <br />
*R_1 is a current limiting resistor transistor base current<br />
*VPLUS_VDD is the power supply for the LED<br />
<br />
<br />
Discussion:<br />
The voltage at the collector of the circuit should fall to a fraction of a volt when the input is high. To acomplish this:<br />
<br />
*Compute the value of R_LED using ohms law and the specifications for the LED.<br />
*Compute the current through the LED.<br />
*The transistor must supply the current, it should be equal approxtely to the input voltage divided by R1 times the beta of the transistor.<br />
<br />
An example calculation would be nice, and will appear later.<br />
<br />
This circuit is sometimes called "grounded-emitter configuration".<br />
<br />
More Information:<br />
*[http://en.wikipedia.org/wiki/Transistor#Switches Transistor From Wikipedia, the free encyclopedia]<br />
<br />
== Transistor High Side Switch ==<br />
<br />
Use this circuit when you wish to turn a load on and off with a voltage at a low current. Note that low side of the load is grounded. The voltage to turn on the switch is equal to the supply voltage ( or perhaps just a bit larger )<br />
<br />
A high side switch is one which switches a circuit on and off at the supply voltage or high side of the circuit. The advantage of a high side switch is that the load is grounded on one side. Compared to the low side switch it needs a higher voltage to drive it, but it also eliminates one resistor of that circuit. It the voltage to drive it is available it may be the circuit of choice. It is often the easy way to drive leds motors and other high current devices from such low power devices as PIC output ports. <br />
<br />
Circuit:<br />
<br />
[[Image:tran_hss.png | Transistor High Side Switch ]]<br />
<br />
Where<br />
*LED is a low power LED<br />
*R_LED is a current limiting resistor for the LED<br />
*Q is a bipolar transistor <br />
*VPLUS_VDD is the power supply for the LED<br />
<br />
The voltage at the collector of the circuit should fall to a fraction of a volt when the input is high. To compute the values in the circuit:<br />
<br />
*Compute the value of R_LED using ohms law and the specifications for the LED.<br />
*The current to drive the circuit is approximately the current to drive the load divided by the beta of the transistor.<br />
<br />
<br />
No resistor is needed into the base of the transistor because as the load draws current the voltage at the base will rise and limit the base current. The input voltage should be about equal to VPLUS_VDD, high compared to that needed for the low side switch.<br />
<br />
== Transistor Emitter Follower ==<br />
<br />
Use this circuit when you have a signal of high impedance ( can supply only a little current ) that you want to connect to another circuit that draws a significant current. The circuit has no voltage gain, but because of the current gain it has a lot of power gain. It is frequently used in the final stage of an amplifier. <br />
<br />
This circuit is a variation of the transistor high side switch. The difference is that we typically drive this circuit in a linear way ( all of the voltages between 0 and the supply voltage ) to make it a linear amplifier.<br />
<br />
The emitter follower is also called a common collector circuit. The Emitter Follower is basically a high side switch, but when we call it an emitter follower we normally think of it as a linear ( analog ) amplifier, rather than as a switch.<br />
<br />
Circuit:<br />
<br />
[[Image:tef.png | Transistor Emitter Follower ]]<br />
<br />
Where<br />
*R_LOAD represents the resistance of the load<br />
*Q is a npn bipolar transistor <br />
*VPLUS_VDD is the power supply for the LED<br />
<br />
The current to drive the circuit is approximately the current to drive the load divided by the beta of the transistor. Use a Darlington connected transistor for a very high beta.<br />
<br />
No resistor is needed into the base of the transistor because as the load draws current the voltage at the base will rise and limit the base current. <br />
<br />
This circuit will only amplify positive voltages, using a pnp transistor you can amplify only negative voltages. Combine the two ( see push pull amplifier ) you can amplify both positive and negative voltages.<br />
<br />
<br />
<br />
Variation of the circuit include: <br />
<br />
*Use of coupling capacitors to amplify ac signals.<br />
*Various other components to bias the transistor.<br />
*Use an op amp buffer with voltage gain at the input, then the emitter follower for high current. In this way a few Milli volts with current on the order of pico amps can drive an output of several volts at an ampere or more. <br />
<br />
More information: <br />
<br />
*[http://www.mines.edu/Academic/courses/physics/phgn217/lab4/lect7/sld013.htm Emitter Follower]<br />
<br />
*[http://en.wikipedia.org/wiki/Common_collector Common collector From Wikipedia, the free encyclopedia]<br />
<br />
== Voltage Divider ==<br />
Voltage Divider<br />
<br />
We use a voltage divider when we have a voltage that is too big and we just want a fraction ( like 1/3 or .33 ) of it. It is like an amplifier with a gain of less than 1. We use two resistors, the output is always a constant fraction of the input voltage.<br />
<br />
Sometimes we use a potentiometer as a voltage divider. This makes the ratio of output to input adjustable. This is how we make a gain control or volume control.<br />
<br />
Circuit:<br />
[[Image:vdivide.png | Voltage Divider ]]<br />
<br />
Where<br />
*R1 resistor 1<br />
*R2 resistor 2<br />
*POT a potentiometer<br />
<br />
The ratio of input to output is: output/input = R2/( R1 + R2 ).<br />
<br />
Discussion<br />
<br />
The equation assumes that the input source is low impedance and the output is high impedance, if this is not true consider using a buffer on the input or the output ( Op Amp Unity Gain Buffer or Transistor Emitter Follower ) For audio applications a so called “log taper” pot may be used as it better matches the way in which we hear. If you want a calibrated control you may use a precision “10 turn precision” pot.<br />
<br />
More information: <br />
*[http://www.seattlerobotics.org/encoder/mar97/basics.html Very Basic Circuits]<br />
*[http://itp.nyu.edu/physcomp/sensors/Schematics/VoltageDivider Voltage Divider]<br />
<br />
== RC Filter ==<br />
<br />
The most basic filters are the RC-High Pass and RC-Low Pass filters. The high pass filter removes DC and low frequencies and the low pass removes high frequencies. <br />
<br />
<br />
'''High Pass''' [[Image:rchighpass.png | RC High Pass Filter]]<br />
'''Low Pass''' [[Image:rclowpass.png | RC Low Pass Filter]]<br />
<br />
Both circuits have the same 3dB frequency or the frequency at which the power of the signal is aproximately halved.<br />
<br />
<math><br />
f_\mathrm{c} = {1 \over 2 \pi \tau } = {1 \over 2 \pi R C}<br />
</math><br />
<br />
The way to remember the two circuits is to think about how the capacitor acts at various signal frequencies. At high frequencies capacitors act like wires. At low frequencies capacitors act like disconnections.<br />
<br />
An important use of low pass filters is for the anti-aliasing circuity on the input of an A/D converter or the output of a D/A converter. An important use of a high pass filter is to remove the DC offset of a signal. For example, it's possible to use a power supply that is +5 to GND to generate a sin from a D/A converter and use a high pass filter to change the sin to a +2.5 to -2.5 signal at the output.<br />
<br />
More information:<br />
*[http://en.wikipedia.org/wiki/Low-pass_filter Low Pass Filter]<br />
*[http://en.wikipedia.org/wiki/High-pass_filter High Pass Filter]<br />
<br />
== Light Emitting Diode ( with current limiting resistor ) ==<br />
<br />
Use this circuit to light low power LEDs<br />
<br />
A light emitting diode can be very sensitive to small voltage changes, just a bit too much voltage and the LED will draw too much current and “burn out”. Thus it is often used with a resistor in series. If we have a 5 volt source of voltage and an LED that is specified for 2.5 volts at 10 ma, then the resistor must have ( 5 – 2.5 ) volts = 2.5 volts and 10 ma. Using ohms law 2.5/10 x 10 ee-3 = 250 ohms.<br />
<br />
A transistor low or high side switch can be used with the resistor if your input cannot supply enough current for the LED.<br />
<br />
Circuit:<br />
[[Image:ledres.jpg | LED and current limiting resistor ]]<br />
<br />
Where<br />
*LED the LED<br />
*R_LED the current limiting resistor<br />
*INPUT voltage source for lighting the LED<br />
<br />
More information: <br />
*[http://www.seattlerobotics.org/encoder/mar97/basics.html Very Basic Circuits ] <br />
*[http://www.iguanalabs.com/1stled.htm Learning About Transistors and LEDs ]<br />
<br />
== Transistor -- Push Pull Circuit ==<br />
<br />
Use when you need current gain and need both positive and negative output.<br />
<br />
A modification of the “transistor emitter follower” that can give both positive and negative outputs. Based on two transistors one npn the other pnp: one pushes the other pulls.<br />
<br />
Circuit:<br />
[[Image:pptrans.png | Push Pull Transistor Circuit]]<br />
<br />
Where<br />
*Q1 transistor 1 need not be a TIP41C but does need to be NPN<br />
*Q2 transistor 2 need not be a TIP42C but does need to be PNP<br />
*R_LOAD represents the load, here it is in the emitter, it could also be placed in the collector circuit<br />
*VPLUS_VDD Power supply voltage, positive.<br />
*VMINUS Power supply voltage, negative.<br />
<br />
Discussion:<br />
Often there are other components for transistor bias or other purposes. The circuit here is really basic. The common transistors used are so called complementary pairs, similar characteristics but one npn and the other pnp. Note that we need both positive and negative power supplies. You can also put the push pull circuit inside the feedback loop of an op amp to get a high current op amplifier. Push pull amplifies can also be made with other types of transistors, tubes, or other components.<br />
<br />
More information: <br />
*[http://www.ecircuitcenter.com/Circuits/pushpull/pushpull.htm Push-Pull Output Stage]<br />
*[http://www.allaboutcircuits.com/vol_6/chpt_6/10.html Class B audio amplifier]<br />
*[http://en.wikipedia.org/wiki/Electronic_amplifier Electronic amplifier From Wikipedia, the free encyclopedia (search on Class B and AB )]<br />
<br />
== Transistors -- Darlington connected ==<br />
<br />
Use a Darlington transistor connection when you want really high current gain. Gain of 1000 is easily in reach. That is 1 ma to 1 amp <br />
This is a useful connection of 2 transistors that together form a transistor of much larger gain. You can also buy Darlington transistors all packaged in a single case with just 3 connections exposed to the outside.<br />
<br />
Circuit:<br />
[[Image:dtrans.png | Darlington Transistor Connection ]]<br />
<br />
Where<br />
*Q1 transistor 1 need not be a 2N3565 but does need to be NPN<br />
*Q2 transistor 2 need not be a 2N3565 but does need to be NPN<br />
*R_LOAD represents the load, here it is in the emitter, it could also be placed in the collector circuit<br />
*VPLUS_VDD Power supply voltage, positive.<br />
<br />
Discussion:<br />
<br />
Often Q1 is a high gain small signal transistor and Q2 a lower gain power transistor. You can use PNP transistors by using a negative power supply. Use a ULN2803 ( or similar chips ) to get 8 darlingtons in one package, useful as low side switches and in conjunction with microcontrollers.<br />
<br />
More information: <br />
* http://en.wikipedia.org/wiki/Darlington_transistor Darlington transistor From Wikipedia, the free encyclopedia]<br />
*[http://www.kpsec.freeuk.com/trancirc.htm Transistor Circuits ( search on Darlington )]<br />
*[http://www.ibiblio.org/kuphaldt/electricCircuits/Semi/SEMI_4.html Lessons In Electric Circuits -- Volume III Chapter 4 BIPOLAR JUNCTION TRANSISTORS Darlington pair ( search on Darlington )]<br />
<br />
== Schmitt Trigger ==<br />
Circuit:<br />
[[Image:opamp_st.png | Schmitt Trigger ]]<br />
<br />
Where<br />
*RIN input resistor -- when this inputs more current than the positive feedback resistor the output switches to the voltage at the input, else it stays at the output voltage it has already reached. Typically lower in value than RFB.<br />
*RFB positive feedback resistor the output voltage is feed back to the input and keeps the output at its current voltage.<br />
<br />
<br />
Discussion:<br />
<br />
The circuit is used to switch between two states even in the presence of noise. This is an somewhat unusual op amp circuit as it uses positive not negative feedback. See the references for a better explanation and variations on the circuit.<br />
Schmidt Triggers are also available as integrated circuits which require no external components.<br />
<br />
More Information:<br />
*[[OpAmp Links]]</div>Yanhttp://www.opencircuits.com/index.php?title=DsPIC30F_5011_Development_Board&diff=16020DsPIC30F 5011 Development Board2008-07-22T10:36:39Z<p>Yan: /* ToDo */ dspic gcc compiler for constant problem</p>
<hr />
<div>==Introduction==<br />
<br />
===Features of dsPIC30F5011===<br />
*2.5 to 5V <br />
*Up to 30MIPs<br />
*High current/sink source I/O pins: 25mA<br />
*DSP Instruction Set<br />
*Dual programming techniques: ICSP and RTSP<br />
*UART: up to 2 modules<br />
*I<sup>2</sup>C: up to 1Mbps<br />
*10-bit A/D, 1.1 Msps <br />
*12-bit A/D, 200 ksps<br />
*44K flash (66Kb), 4Kb RAM, 1Kb EEPROM<br />
*No DAC<br />
*Pin-to-pin compatible with other dsPICs<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 1.1 Comparison with Compatible dsPICs<br />
! dsPic !! Price<br>US$ !! MIPs<br />
! Flash<br>(kB)!! RAM<br>(kB) !! EEPROM<br>(kB)<br />
! I/O !! ADC<br>12-bit !! IC !! OC !! Motor<br>Ctrl !! Timers<br />
! QEI !! UART !! SPI !! I2C !! CAN !! Codec<br />
|- <br />
| 30F5011 || 5.91 || 30<br />
| 66 || 4 || 1<br />
| 52 || 16 || 8 || 8 || 0 || 5x16bit<br>2x32bit<br />
| 0 || 2 || 2 || 1 || 2 || 1<br />
|-<br />
| 30F6011A || 7.73 || 30<br />
| 132 || 6 || 2<br />
| 52 || 16 || 8 || 8 || 0 || 5x16bit<br>2x32bit<br />
| 0 || 2 || 2 || 1 || 2 || 0<br />
|-<br />
| 30F6012A || 7.85 || 30<br />
| 144 || 8 || 4<br />
| 52 || 16 || 8 || 8 || 0 || 5x16bit<br>2x32bit<br />
| 0 || 2 || 2 || 1 || 2 || 1<br />
|- <br />
| 33FJ128GP206 || 4.62 || 40<br />
| 128 || 8 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 1 || 0 || 1<br />
|-<br />
| 33FJ128GP306 || 4.81 || 40<br />
| 128 || 16 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 2 || 0 || 1<br />
|-<br />
| 33FJ128GP706 || 5.49 || 40<br />
| 128 || 16 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 2 || 2 || 1<br />
|-<br />
| 33FJ128MC506 || 4.97 || 40<br />
| 128 || 8 || 0<br />
| 53 || 16 || 8 || 8 || 8 || 9x16bit<br>4x32bit<br />
| 1 || 2 || 2 || 2 || 1 || 0<br />
|-<br />
| 33FJ128MC706 || 5.38 || 40<br />
| 128 || 16 || 0<br />
| 53 || 16 || 8 || 8 || 8 || 9x16bit<br>4x32bit<br />
| 1 || 2 || 2 || 2 || 1 || 0<br />
|-<br />
| 33FJ256GP506 || 6.11 || 40<br />
| 256 || 16 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 2 || 1 || 1<br />
|-<br />
|}<br />
<br />
===Web Page===<br />
*[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2529&param=en024856 Microchip Official Website]<br />
<br />
===Forum===<br />
*[http://direct.forum.microchip.com/default.aspx Microchip]: Official forum by Microchip<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=49 MPLAB ICD 2]: Subforum on ICD 2 programmer<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=57 MPLAB IDE]: Subforum on IDE<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=101 MPLAB C30 Compiler, ASM30, Link30 forum]: Subforum on C compiler. Refer to [http://ww1.microchip.com/downloads/en/DeviceDoc/C30_Users_Guide_51284e.pdf MPLAB C30 C Compiler User's Guide] Chapter 3<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=153 dsPIC30F Topics]: Subformum on dsPIC30F<br />
*[http://www.gnupic.org/ GNUPIC]: Discussion on PIC in Linux Systems<br />
**[http://www.linuxhacker.org/cgi-bin/ezmlm-cgi?1:dds:5443#b Debian]<br />
*[http://www.htsoft.com/forum/all/ubbthreads.php/Cat/0/C/6 HI-TECH Software Forum]: Discussion on dsPICC, a C compiler developed by HI-TECH<br />
*[http://piclist.com/techref/piclist/index.htm PICList]: Discussion on older PIC systems (not dsPIC)<br />
*[http://groups.google.com/group/pickit-devel PicKit]: Discussion on PICkit/PICkit 2 programmers<br />
*[http://sourceforge.net/forum/forum.php?forum_id=382005 FreeRTOS Real Time Kernel]: Open Discussion and Support on FreeRTOS <br />
<br />
===References===<br />
*dsPIC30F<br />
**[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2574 dsPIC30F Family Reference Manual Sections]: Contains detailed descriptions on dsPIC30F register definitions and example codes<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80169E.pdf dsPIC30F Family Reference Manual Errata (Use with revision 70046B only)]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70116F.pdf dsPIC30F5011, dsPIC30F5013 Data Sheet]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80210e.pdf dsPIC30F5011/5013 Rev. A1/A2 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80223D.pdf dsPIC30F5011/5013 Rev. A3 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70102G.pdf Flash Programming Specification]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70157B.pdf dsPIC30F Programmer's Reference Manual]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80170a.pdf dsPIC30F Programmer's Reference Manual Errata (use with revision DS70030E only)]<br />
<br />
*dsPIC33F<br />
**[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2573 dsPIC33F Family Reference Manual Sections]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70165E.pdf dsPIC33F Family Data Sheet]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80279B.pdf dsPIC33F Rev. A2 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80306A.pdf dsPIC33FJXXXGPX06/X08/X10 Rev. A2 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70152C.pdf Flash Programming Specification]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70172A.pdf dsPIC30F to dsPIC33F Conversion Guidelines]<br />
*ICD2 Programmer<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/51331B.pdf ICD2 User's Guide] <br />
*MPLAB<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/51519B.pdf MPLAB IDE User's Guide]<br />
*C30 Compiler<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/C30_Users_Guide_51284e.pdf MPLAB C30 C Compiler User's Guide]: Contains commands for using pic30-elf-gcc <br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/16bit_Language_Tool_Libraries_51456c.pdf 16-bit Language Tools Libraries]: Contains summaries and examples of using DSP libraries, standard C libraries and device libraries<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/Asm30_Link_Util_51317e.pdf MPLAB ASM30, MPLAB LINK30 and Utilities User's Guide]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/51322d.pdf dsPIC30F Language Tools Quick Reference Card]<br />
<br />
===Code Examples===<br />
*[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1408 Microchip Example Codes for dsPic]<br />
<br />
<br />
==Programming Methods==<br />
*There are 2 programming methods: In-Circuit Serial Programming (ICSP) and Run-Time Self-Programming (RTSP)<br />
*ICSP allows the devices to be programmed after being placed in a circuit board.<br />
*RTSP allows the devices to be programmed when an embedded program is already in operation.<br />
<br />
===ICSP: External Programmer (ICD2)===<br />
*Two types of ICSP are available: '''ICSP''' and '''Enhanced ICSP'''. Both of them require setting MCLR# to V<sub>IHH</sub> (9V – 13.25V).<br />
*Standard ICSP<br />
**Use external programmer (e.g. MPLAB<sup>®</sup> ICD 2, MPLAB<sup>®</sup> PM3 or PRO MATE<sup>®</sup> II) only.<br />
**Required low-level programming to erase, program and verify the chip.<br />
**Slower, because codes are serially executed.<br />
**Program memory can be erased using ''Normal-Voltage'' (4.5 – 5.5V) or ''Low-Voltage'' (2.5V – 4.5V).<br />
<br />
*Enhanced ICSP<br />
**Use external programmer and '''Programming Executive''' (PE).<br />
**PE is stored in the on-chip memory.<br />
**PE allows faster programming.<br />
**PE can be downloaded to the chip by external programmer using the standard ICSP method.<br />
**PE contains a small command set to erase, program and verify the chip, avoiding the need of low-level programming.<br />
<br />
====Hardware Interface====<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.1 Pin Used by ICSP<br />
! Pin Label !! Function !! Pin Number<br />
|- <br />
| MCLR# || Programming Enable|| 7<br />
|-<br />
| V<sub>DD</sub> || Power Supply || 10, 26, 38, 57<br />
|-<br />
| V<sub>SS</sub> || Ground || 9, 25, 41, 56<br />
|- <br />
| PGC || Serial Clock || 17<br />
|-<br />
| PGD || Serial Data || 18<br />
|-<br />
|}<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.2 Available Programmers in the Market<br />
! Product Name<br />
! Interface with PC<br />
! Interface with Device<br />
! Price (US)<br />
! Postage (US)<br />
! Total (US)<br />
|- <br />
| [http://direct.www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en010046&part=DV164005 MPLAB<sup>®</sup> ICD 2]<br />
| USB or RS232<br />
| [http://www.microchip.com/Microchip.WWW.SecureSoftwareList/secsoftwaredownload.aspx?device=en010046&lang=en&ReturnURL=http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en010046&part=DV164005# 6-PIN RJ-12 connector]<br />
| $159.99<br />
| -<br />
| -<br />
|-<br />
| [http://www.etekronics.com/product_info.php?cPath=24&products_id=48 Full Speed USB Microchip ICD2<br> Debugger and Programmer]<br />
| USB<br />
| 6-PIN ICSP connector<br>6-PIN RJ-12 connector<br />
| $72.00<br />
| $12.00<br />
| $84.00<br />
|-<br />
| [http://www.etekronics.com/product_info.php?cPath=24&products_id=47 Mini Microchip Compatible ICD2<br> Debugger and Programmer]<br />
| RS232<br />
| 6-PIN ICSP connector<br>6-PIN RJ-12 connector<br />
| $45.00<br />
| $10.00<br />
| $55.00<br />
|-<br />
| [http://www.inexglobal.com/microcontroller.php ICDX30]<br />
| RS232<br />
| 6-pin RJ-11<br />
| $51.00<br />
| $47.46<br />
| $98.46<br />
|-<br />
| *[http://www.sure-electronics.net Clone Microchip ICD2] (Now Using)<br />
| USB<br />
| 6-pin flat cables<br />
| $30.00<br />
| $12.00<br />
| $42.00<br />
|-<br />
|}<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.3 DIY ICD 2 Programmer Circuit<br />
! Source !! Schematic !! PIC16F877A Bootloader<br />
|- <br />
| [http://membres.lycos.fr/silicium31/Electronique/PIC/FreeIcdEnglish.htm Patrick Touzet]<br />
| [http://membres.lycos.fr/silicium31/Electronique/PIC/ICD2%20V1.3.pdf Yes]<br />
| [http://membres.lycos.fr/silicium31/Electronique/PIC/ICD2_FW.zip HEX]<br />
|-<br />
| [http://www.nebadje.org/doku.php?id=neblab:icd2clone Nebadje]<br />
| [http://people.ee.ethz.ch/~jbiveron/nebadje/ICD2_DOC.pdf Yes]<br />
| [http://people.ee.ethz.ch/~jbiveron/nebadje/ICD2_FW.zip Zip]<br />
|-<br />
|}<br />
<br />
====Software Interface====<br />
*The program can be written and compiled in an Integrated Development Environment (IDE) using either Assembly or C. The complied codes are then loaded to the device through the external programmer.<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.4 Summary of IDE<br />
! Product Name !! Features !! OS !! Price (US$)<br />
|- <br />
| [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en019469&part=SW007002 MPLAB<sup>®</sup> IDE]<br />
| Assembler Only<br />
| Windows<br />
| Free<br />
|-<br />
| [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en010065&part=SW006012 MPLAB<sup>®</sup> C30]<br />
| Assembler and C-Compiler<br />
| Windows<br />
| $895.00 (Free student version<sup>1</sup>)<br />
|-<br />
| [http://linux.softpedia.com/get/Science-and-Engineering/Electronic-Design-Automation-EDA-/Piklab-8099.shtml Piklab 0.12.0]<br />
| Assembler and C-Compiler<br />
| Linux<br />
| Free<sup>2</sup><br />
|}<br />
# Full-featured for the first 60 days. After 60 days, some code optimization functions are disabled. The compiler will continue to function after 60 days, but code size may increase.<br />
# The current version supports external programmer ICD 2, but not yet tested.<br />
<br />
===RTSP: COM Port (Bootloader)===<br />
*RTSP works in normal voltage (MCLR# no need to raise to V<sub>IHH</sub>).<br />
*No literature has mentioned the incorporation of Programming Executive (PE). Presumably, since Enhanced ICSP needs to set MCLR# to V<sub>IHH</sub>, RTSP cannot use PE.<br />
*Refer to [http://www.opencircuits.com/DsPIC30F_5011_Development_Board#Bootloader_Development bootloader section].<br />
<br />
<br />
==IC Requirements==<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 3.1 IC Requirements<br />
! Part No. !! Description <br />
! Min Temp !! Max Temp !! Min Volt !! Max Volt !! Typ Cur !! Max Cur<br />
|-valign="top"<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/70116F.pdf dsPIC30F5011-30I/PT] || uP <br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 2.5V <sup>[1]</sup>|| 5.5V<br />
| 145mA || 217mA<br />
|-<br />
| [http://datasheets.maxim-ic.com/en/ds/MAX3222-MAX3241.pdf MAX3232ESE] || RS232 driver<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 3.0V || 5.5V<br />
| 0.3mA || 1.0mA<br />
|-<br />
| [http://www.national.com/ds.cgi/DS/DS3695.pdf DS3695N] || RS485 driver<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 4.75V || 5.25V<br />
| 42mA || 60mA<br />
|-<br />
| [http://focus.ti.com/lit/ds/symlink/dac6574.pdf DAC6574IDGS] || 10-bit Quad-DAC I<sup>2</sup>C<br />
| -40<sup>o</sup>C || 105<sup>o</sup>C<br />
| 2.7V || 5.5V<br />
| 0.6mA || 0.9mA<br />
|-<br />
| [http://www.semiconductors.philips.com/acrobat/datasheets/74HC_HCT14_3.pdf 74HC14D] || Quad-Schmitt Trigger<br />
| -40<sup>o</sup>C || 125<sup>o</sup>C<br />
| 2.0V || 6.0V<br />
| || 0.02mA<br />
|-<br />
| '''Overall''' || <br />
| '''-40<sup>o</sup>C''' || '''85<sup>o</sup>C'''<br />
| '''4.75V''' || '''5.25V'''<br />
| || '''<300mA <sup>[2]</sup>'''<br />
|-<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/70165E.pdf dsPIC33FJ128GP306-I/PT] || uP <br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 3.0V <sup>[1]</sup>|| 3.6V<br />
| 74mA || 250mA<br />
|-<br />
| [http://www.analog.com/UploadedFiles/Data_Sheets/ADM3485E.pdf ADM3485EARZ] || RS485 driver<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 3.0V || 3.6V<br />
| 1.1mA || 2.2mA<br />
|-<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/21203N.pdf 24LC256-I/SN] || 256kBits I2C EEPROM<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 2.5V || 5.5V<br />
| 400uA || 3mA<br />
|-<br />
| [http://www.national.com/ds.cgi/LM/LM3940.pdf LM3940IMP-3.3] || 5V-3.3V Regulator<br />
| -40<sup>o</sup>C || 125<sup>o</sup>C<br />
| 5.0V || 7.5V<br />
| 10mA || 250mA<br />
|-<br />
|}<br />
#Minimum voltage measured is 3.3V (with 2 LEDs blinking) running at 30MHz.<br />
#Measured current at 5V is 180mA (with 2 LEDs blinking only)<br />
<br />
<br />
==Development Environment==<br />
<br />
===Windows===<br />
<br />
[[Image:PIC_setup_win.JPG]]<br />
<br />
*C-Compiler, Assembler and Linker are under GNU license.<br />
**MPLAB C30 C Compiler (*.c -> *.s)<br />
**MPLAB ASM30 Assembler (*.s -> *.o)<br />
**MPLAB LINK30 Linker (*.o -> *.bin)<br />
<br />
*PA optimizer, simulator, runtime libraries, header files, include files, and linker scripts are not covered by GNU. Reference is [http://direct.forum.microchip.com/tm.aspx?m=107208 here].<br />
<br />
*Microchip has integrated ASM30, LINK30, assembly header files, linker scripts in MPLAB IDE, which is free for download.<br />
*MPLAB C30 costs US$895. A 60-day free student version is also available. After 60-days, the optimizer is automatically disabled, while other tools can still function properly. Refer to Table 2.4.<br />
<br />
*C-libraries contained in C30 includes (Refer to [http://ww1.microchip.com/downloads/en/DeviceDoc/16bit_Language_Tool_Libraries_51456c.pdf 16-Bit Language Tools Libraries] from Microchip).<br />
<br />
<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 4.1 C Libraries in MPLAB C30<br />
! Library !! Directory <br>(\\Microchip\MPLAB C30) !! Major functions<br />
|-valign="top"<br />
| DSP Library <br>(e.g. libdsp-coff.a)<br />
| \lib <br> \src\dsp <br> \support\h<br />
| Vector, Matrix, Filter, etc.<br />
|-valign="top"<br />
| 16-Bit Peripheral Libraries <br>(e.g. libp30F5011-coff.a)<br />
| \lib <br> \src\peripheral <br> \support\h<br />
| ADC12, IOPort, UART, I<sup>2</sup>C, etc.<br />
|-valign="top"<br />
| Standard C Libraries <br>(e.g. libc-coff.a, libm-coff.a, libpic-coff.a)<br />
| \lib <br> \src\libm <br> \include<br />
| stdio.h, time.h, float.h, math.h, <br />
|-valign="top"<br />
| MPLAB C30 Built-in Functions<br />
| none<br />
| _buildin_addab, _buildin_add, _buildinmpy, etc<br />
|-<br />
|}<br />
<br />
===Linux===<br />
<br />
[[Image:PIC_setup_linux.JPG]]<br />
<br />
*C Compiler, Assembler and Linker are under GNU license.<br />
**The code can be downloaded from Microchip at [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en023073 here].<br />
**Current MPLAB ASM30 Assembler: v2.04<br />
**Current MPLAB C30 Compiler: v2.04<br />
<br />
*[http://gcc.gnu.org/ml/gcc/2005-02/msg01144.html John Steele Scott] has made templates that can be readily used by Debian-based systems. <br />
*For v1.32, the necessary conversion to *.deb has been done already at [http://noel.feld.cvut.cz/dspic/ here].<br />
**Download '''pic30-1.32-debian.tar.bz2''' for Template v1.32.<br />
**Download '''pic30-binutils_1.32-1_i386.deb''' for the assember.<br />
**Download '''pic30-gcc_1.32-1_i386.deb''' for the compiler.<br />
*For v2.00<br />
**goto http://www.baycom.org/~tom/dspic/<br />
**download pic30-gcc-2.00-1.i386.rpm and pic30-binutils-2.00-1.i386.rpm<br />
**convert to deb files<br />
**install these two deb files<br />
*For v3.01, convert the Toolchain following instructions at [http://www.nabble.com/Debian-templates-for-dsPIC-build-toolchain-3.01-tf4308624.html here]<br />
**Pre-install these packages: dpkg-dev, debhelper, bison, flex, sysutils, gcc-3.3, fakeroot<br />
***cmd: '''sudo apt-get install dpkg-dev debhelper bison flex sysutils gcc-3.3 fakeroot'''<br />
**Download and unzip template: '''pic30-3.01.tar.bz2'''<br />
**Download assembler: '''mplabalc30v3_01_A.tar.gz'''. Save under /pic30-3.01/pic30-binutils-3.01/upstream/<br />
**Download c-compiler: '''mplabc30v3_01_A.tgz'''. Save under /pic30-3.01/pic30-gcc-3.01/upstream/<br />
**Install MPLAB_C30_v3_01-StudentEdition under Windows<br />
**Copy directories /include, /lib, /support, and /bin/c30_device.info to pic30-3.01/pic30-support-3.01/upstream/<br />
**Pack pic30-binutils into deb file<br />
***goto /pic30-3.01/pic30-binutils-3.01/<br />
***type cmd: '''dpkg-buildpackage -rfakeroot -b'''<br />
**Pack pic30-gcc-3.01 into deb file<br />
***goto /pic30-3.01/pic30-gcc-3.01/<br />
***type cmd: '''dpkg-buildpackage -rfakeroot -b'''<br />
**Pack pic30-gcc-3.01 into deb file<br />
***goto /pic30-3.01/pic30-support-3.01/<br />
***type cmd: '''dpkg-buildpackage -rfakeroot -b'''<br />
**install pic30-binutils_3.01-1_i386.deb<br />
***type cmd: '''sudo dpkg -i pic30-binutils_3.01-1_i386.deb'''<br />
**install pic30-gcc_3.01-1_i386.deb<br />
***type cmd: '''sudo dpkg -i pic30-gcc_3.01-1_i386.deb'''<br />
**install pic30-support_3.01-1_all.deb<br />
***type cmd: '''sudo dpkg -i pic30-support_3.01-1_all.deb'''<br />
*'''Important Note''': Only the compiler is free. The header files and library are owned by Microchip. <br />
**Thomas Sailer suggested to download the Student version of C30 compiler and then build the libraries without source code. A package template for Fedora system is available [http://www.baycom.org/~tom/dspic/ here].<br />
**Instructions for filling the upstream direction is available [http://forum.microchip.com/printable.aspx?m=139360 here].<br />
**Alteratively, [https://gna.org/projects/pic30-libc/ Stephan Walter] has started a project to develop C Runtime Library for dsPIC. <br />
***Current libraries in version 0.1.1 include: assert.h, cdefs.h, ctype.h, errno.h, inttypes.h, stdint.h, stdio.h, stdlib.h, string.h<br />
<br />
*Burning Program Codes to Target Board<br />
#Use 'dspicprg and dspicdmp' utilities developed by [http://homerreid.ath.cx/misc/dspicprg/ Homer Reid] to burn hex code (*.hex) to devices. See Reference [http://forum.microchip.com/tm.aspx?m=94243 here]. Through serial port only?<br />
#Use [http://piklab.sourceforge.net/ Piklab IDE]. Details on file format not known.<br />
#Use [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en019469&part=SW007002 MPLAB IDE] to burn hex code (*.hex) to devices.<br />
<br />
===Code Optimization===<br />
*Below is a comparsion between different optimization levels for the project including drivers for 2 projects.<br />
<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 4.2 Comparison between differnt optimization levels<br />
! Optimization !! Description !! Project 1<br>Code Size<br>(byte) !! Project 1<br>Data Usage<br>(byte) !! Project 2<br>Code Size<br>(byte) !! Project 2<br>Data Usage<br>(byte)<br />
|-valign="top"<br />
| O0 <br />
| No optimization<br>Fastest Compilation<br />
| 6222 (9%) || 178 (4%) || 26,037 (38%) || 710 (17%)<br />
|-valign="top"<br />
| O1 <br />
| Optimize<br> Tries to reduce code size and execution time.<br />
| 4473 (6%) || 178 (4%) || 22,290 (32%) || 710 (17%)<br />
|-valign="top"<br />
| O2 <br />
| Optimize even more<br> Performs nearly all supported optimizations <br>that do not involve a space-speed trade-off. <br>Increases both compilation time and the <br>performance of the generated code.<br />
| 4422 (6%) || 178 (4%) || 21,993 (32%) || 710 (17%)<br />
|-valign="top"<br />
| O3 <br />
| Optimize yet more. <br>O3 turns on all optimizations specified by O2 <br>and also turns on the inline-functions option.<br />
| 4485 (6%) || 178 (4%) || 22,176 (32%) || 710 (17%)<br />
|-valign="top"<br />
| Os <br />
| Optimize for size. <br>Os enables all O2 optimizations that do not <br>typically increase code size. It also performs <br>further optimizations designed to reduce code <br>size.<br />
| 4356 (6%) || 178 (4%) || 21,885 (32%) || 710 (17%)<br />
|-<br />
|}<br />
<br />
<br />
==Software Architecture==<br />
+--------+--------+--------+--------+--------+<br />
Application | Task 1 | Task 2 | Task 3 | Task 4 | Task 5 |<br />
+--------+--------+--------+--------+--------+<br />
| POSIX API |<br />
+-------------------+------------------------+<br />
OS | Coroutine | FreeRTOS Scheduler |<br />
+-------------------+------------------------+<br />
| Drivers |<br />
+------+-----+-----+--------+-------+--------+<br />
Hardware | UART | ADC | DAC | EEPROM | PWM | TIMERS | <br />
+------+-----+-----+--------+-------+--------+<br />
*Currently, operating system is based on [http://www.freertos.org/ FreeRTOS] incorporating coroutine developed by [http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html Simon Tatham]<br />
*Software Drivers are to be developed to allow users at Application Level to use the hardware (e.g. ADC, DAC, UART, EEPROM etc) through the OS.<br />
*The interface between the drivers and the OS is based on [http://www.die.net/doc/linux/man/man2/ POSIX standard] (e.g. open(), write(), read(), ioctl(), usleep() etc).<br />
*The most up-to-date development can be found at repository [http://chungyan5.no-ip.org/vc/?root=freertos_posix freertos_posix]<br />
<br />
<br />
==Programming Tips==<br />
<br />
===Memory Map for 5011===<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 6.1 Memory Location<br />
! Type !! Start Address !! End Address !! Size<br />
|-valign="top"<br />
| Flash || 0x000000 ||0x00AFFF || 44K<sup>[1]</sup><br />
|-valign="top"<br />
| +--Flash: Reset Vector || 0x000000 ||0x000003 || 4<br />
|-valign="top"<br />
| +--Flash: Interrupt Vector Table || 0x000004 ||0x00007F || 124<br />
|-valign="top"<br />
| +--Flash: Alternate Vector Table || 0x000084 ||0x0000FF || 124<br />
|-valign="top"<br />
| +--Flash: User Program || 0x000100 ||0x00AFFF || 43.7K<br />
|-valign="top"<br />
| EEPROM || 0x7FFC00 || 0x7FFFFF || 1K<sup>[2]</sup><br />
|-valign="top"<br />
| Programming Executive || 0x800000 || 0x8005BF || 1472<br />
|-valign="top"<br />
| Unit ID || 0x8005C0 || 0x8005FF || 64<br />
|-valign="top"<br />
| Config Registers || 0xF80000 || 0xF8000F || 16<br />
|-valign="top"<br />
| Device ID || 0xFF0000 || 0xFF0003 || 4<br />
|-<br />
|}<br />
[1] Each address is 16-bit wide. Every two addresses correspond to a 24-bit instruction. Each even address contains 2 valid bytes; each odd address contains 1 valid byte plus 1 phathom byte.<br><br />
[2] Each address is 8-bit wide.<br />
<br />
===Data Location===<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 6.2 Data Location<br />
! Type !! Description !! Example<br />
|-valign="top"<br />
| _XBSS(N) <sup>[1]</sup><br />
| RAM Data in X-memory, aligned at N, no initilization<br />
| int _XBSS(32) xbuf[16];<br />
|-valign="top"<br />
| _XDATA(N) <sup>[1]</sup><br />
| RAM Data in X-memory, aligned at N, with initilization<br />
| int _XDATA(32) xbuf[] = {1, 2, 3, 4, 5};<br />
|-valign="top"<br />
| _YBSS(N) <sup>[1]</sup><br />
| RAM Data in Y-memory, aligned at N, no initilization<br />
| int _YBSS(32) ybuf[16];<br />
|-valign="top"<br />
| _YDATA(N) <sup>[1]</sup><br />
| RAM Data in Y-memory, aligned at N, with initilization<br />
| int _YDATA(32) ybuf[16] = {1, 2, 3, 4, 5};<br />
|-valign="top"<br />
| __attribute__((space(const)))<br />
| Flash ROM data, constant, accessed by normal C<br>statements, but 32K max.<br />
| int i __attribute__((space(const))) = 10;<br />
|-valign="top"<br />
| __attribute__((space(prog)))<br />
| Flash ROM data, read/write by program space visibility<br>window (psv)<br />
| int i __attribute__((space(prog)));<br />
|-valign="top"<br />
| __attribute__((space(auto_psv)))<br />
| Flash ROM data, read by normal C statements, write<br>by accessing psv<br />
| int i __attribute__((space(auto_psv)));<br />
|-valign="top"<br />
| __attribute__((space(psv)))<br />
| Flash ROM data, read/write by (psv)<br />
| int i __attribute__((space(psv)));<br />
|-valign="top"<br />
| _EEDATA(N) <sup>[1]</sup><br />
| ROM Data in EEPROM, aligned at N, read/write with psv<br />
| int _EEDATA(2) table[]={0, 1, 2, 3, 5, 8};<br />
|-valign="top"<br />
| _PERSISTENT<br />
| RAM Data, data remain after reset<br />
| int _PERSISTENT var1, var2;<br />
|-valign="top"<br />
| _NEAR<br />
| RAM Data at near section<br />
| int _NEAR var1, var2;<br />
|-valign="top"<br />
| _ISR<br />
| Interrupt service rountine<br />
| void _ISR _INT0Interrupt(void);<br />
|-valign="top"<br />
| _ISRFAST<br />
| Fast interrupt service rountine<br />
| void _ISRFAST _T0Interrupt(void);<br />
|-<br />
|}<br />
#N must be a power of two, with a minimum value of 2.<br />
<br />
===Configuration Bits===<br />
----<br />
*System clock source can be provided by:<br />
#Primary oscillator (OSC1, OSC2)<br />
#Secondary oscillator (SOSCO and SOSCI) with 32kHz crystal<br />
#Internal Fast RC (FRC) oscillator at 7.37MHz (7372800Hz)<br />
#Low-Power RC (LPRC) oscillator (Watchdog Timer) at 512 kHz.<br />
*These clock sources can be incorporated with interal Phase-locked-loop (PLL) x4, x8 or x16 to yield the osciallator frequrence F<sub>OSC</sub><br />
*The system clock is divided by 4 to yield the internal instruction cycle clock, F<sub>CY</sub>=F<sub>OSC</sub>/4<br />
*FRC with PLLx16 is used to achieve F<sub>CY</sub>=29.49MHz (29491200Hz or 30MIPS)<br />
<br />
//The code (MACRO) below is to be placed at the top of program (before main)<br />
_FOSC(CSW_FSCM_OFF & FRC_PLL16);<br />
_FWDT(WDT_OFF); //Turn off Watchdog Timer<br />
_FBORPOR(PBOR_ON & BORV_27 & MCLR_DIS & PWRT_16);<br />
_FGS(CODE_PROT_OFF); //Disable Code Protection<br />
<br />
===Timer===<br />
<br />
----<br />
*Each timer is 16-bit (i.e. counting from 0 to 65535).<br />
*Timer 2 and 3 can be incorporated together to form a 32-bit timer.<br />
*Prescale is the ratio between timer counts and system clock counts. Prescales of 1:1, 1:8, 1:64 and 1:256 are available.<br />
*Timers may be used to implement free time clock or mesaure time.<br />
<br />
====Free Time Clock====<br />
*Let required time for ticking be PERIOD.<br />
*Number of instruction cycles during PERIOD = PERIOD*F<sub>CY</sub> cycles<br />
*Using a prescale of 1:x, the timer period count register = # of cycles/x<br />
*e.g. PERIOD = 10ms; # of cycles = 10ms*30MHz = 300000 cylces; Using 1:64 Prescale, register setting = 300000/64 = 4688<br />
void time_init(void){<br />
TMR1 = 0; // Clear register<br />
PR1 = 4688; // Set period<br />
//============================================================<br />
_T1IF = 0; // Clear interrupt flag<br />
_T1IE = 1; // Enable interrupts<br />
//============================================================<br />
T1CONbits.TCS = 0; // Use internal clock source<br />
T1CONbits.TCKPS = 2; // Prescale Select 1:64<br />
T1CONbits.TON = 1; // Start the timer <br />
}<br />
//********************************************************************<br />
void _ISRFAST _T1Interrupt(void){<br />
_T1IF = 0; // Clear interrupt flag<br />
//Place user code here<br />
}<br />
<br />
====Time Measurement====<br />
*To measure the time taken for action(), use the code below:<br />
unsigned int measure_time(void){ <br />
PR3 = 0xFFFF; // Set counter to maximum<br />
_T3IF = 0; // Clear interrupt flag<br />
_T3IE = 0; // Disable interrupt<br />
T3CONbits.TON = 1; // Start the timer, TMR3 count up<br />
TMR3 = 0; //Clear TMR3 to start count up<br />
//====================================================<br />
//Add code here to wait for something to happen<br />
action();<br />
//====================================================<br />
T3CONbits.TON = 0; //Stop the timer<br />
//====================================================<br />
return (unsigned int) TMR3/FCY; //TMR/FCY yields the actual time<br />
}<br />
<br />
===Interrupt===<br />
<br />
----<br />
*Registers are involved in Interrupts includes: <br />
#Interrupt Flag Status (IFS0-IFS2) registers<br />
#Interrupt Enable Control (IEC0-IEC2) registers<br />
#Interrupt Priority Control (IPC0-IPC10) registers<br />
#Interrupt Priority Level (IPL) register<br />
#Global Interrupt Control (INTCON1, INTCON2) registers<br />
#Interrupt vector (INTTREG) register<br />
*User may assign priority level 0-7 to a specific interrupt using IPC. Setting priority to 0 disable a specific interrupt. Level 7 interrupt has the highest priority.<br />
*Current priority level is stored in bit<7:5> of Status Register (SR). Setting Interrupt Priority Level (IPL) to 7 disables all interrupts (except traps). <br />
*sti() and cli() can be defined to enable and disable global interrupts for time critical functions:<br />
#define IPL ( 0x00e0 )<br />
#define cli() SR |= IPL //Set IPL to 7<br />
#define sti() SR &= ~IPL //Set IPL to 0<br />
//============================================================<br />
char adc_ioctl(unsigned char request, unsigned char* argp){<br />
//...<br />
cli(); //Disable global interrupt<br />
for(;ch<=argp[0];ch++)<br />
adc_add_ch(argp[ch]); //Add adc channels<br />
sti(); //Enable global interrupt<br />
//...<br />
return 0;<br />
}<br />
*dsPic30F has an [http://ww1.microchip.com/downloads/en/DeviceDoc/80223D.pdf errate note] on the Interrupt Controller. When Nested Interrupt is turned on (NSTDIS=0 by default), a high priority interrupt negating a low priority interrupt may result in an Address Error.<br />
*To work around the problem, it is suggested by Microchip to use the following MACRO to protect:<br />
# the clearing of Interrput Flag<br />
# the disabling of Interrupt Enable<br />
# the lowering of Interrupt Priority <br />
# the modification of IPL in Status Register to 1-6<br />
#define DISI_PROTECT(X) { \<br />
__asm__ volatile ("DISI #0x1FFF");\<br />
X; \<br />
DISICNT = 0; \<br />
}<br />
*For example,<br />
void _ISR _T1Interrupt( void )<br />
{<br />
DISI_PROTECT(IFS0bits.T1IF = 0);<br />
//do something here...<br />
}<br />
<br />
===UART===<br />
<br />
----<br />
*5011 provides two UART channels UxART, for x=1, 2.<br />
*UxMODE, UxSTA, UxBRG are registers used to set the mode, indicate the status, and set the baud rate respectively.<br />
*For UART communications compatiable with RS232 standard, an external driver (e.g. MAX3232ESE) is needed.<br />
*For UART communications compatiable with RS485 standard, an external driver (e.g. DS3695N) is needed.<br />
====Auto baud rate detection====<br />
*The method is provided by [http://www.opencircuits.com/DsPIC30F_5011_Development_Board ingenia bootloader].<br />
*The PC sends a ASCII character 'U' (0x55) to the target board.<br />
*On the first rising edge of the start bit, the target board starts the timer.<br />
*At the fifth rising edge, the timer is stopped, let the count number be ''t_count''. <br />
**The measured period corresponds to 8 bits transmitted at a baud rate ''uxbrg''.<br />
_ _ _ _ _ _<br />
_|S|_|1|_|1|_|1|_|1|_|S|_ (S = Start Bit)<br />
<---------------><br />
Measured Time<br />
*The relationship between ''uxbrg'' and ''TMR'' is<br />
Measured Time (in seconds) = t_count/F<sub>cy</sub><br />
uxbrg = 1/(Measured Time/8)<br />
= 8*F<sub>cy</sub>/t_count<br />
*Since UxBRG is computed by:<br />
UxBRG = (F<sub>cy</sub>/(16*Baudrate)) -1<br />
= (F<sub>cy</sub>/(16*8*F<sub>cy</sub>/t_count)) -1<br />
= t_count/128 -1<br />
*The following is the code for auto baud rate detection for U2ART:<br />
unsigned int uart2_autobaud(void){<br />
U2MODEbits.ABAUD = 1; //Enable Autobaud detect from U2RX (from IC2 if 0)<br />
U2MODEbits.UARTEN = 1; //U2ART enable<br />
//Timer 3 Config==========================================================<br />
PR3 = 0xFFFF; // Set counter to maximum<br />
_T3IF = 0; // Clear interrupt flag<br />
_T3IE = 0; // Disable interrupt<br />
T3CONbits.TON = 1; // Start the timer, TMR3 count up<br />
//Input Capture Config====================================================<br />
IC2CONbits.ICM = 3; //Detect rising <br />
_IC2IF = 0; //Clear interrupt flag<br />
_IC2IE = 0; //Disable interrupt<br />
//Start Auto baud detection===============================================<br />
unsigned int i=0;<br />
cli(); //Disable Global Interrupt<br />
while(!_IC2IF); //1st rising edge detected<br />
TMR3 = 0; //Clear TMR3 to start count up<br />
_IC2IF = 0; //Clear interrupt flag<br />
while(!_IC2IF); //2nd rising edge detected<br />
_IC2IF = 0; //Clear interrupt flag<br />
while(!_IC2IF); //3rd rising edge detected<br />
_IC2IF = 0; //Clear interrupt flag<br />
while(!_IC2IF); //4th rising edge detected<br />
_IC2IF = 0; //Clear interrupt flag<br />
while(!_IC2IF); //5th rising edge detected<br />
_IC2IF = 0; //Clear interrupt flag<br />
T3CONbits.TON = 0; //Stop the timer<br />
sti(); //Enable Global Interrupt<br />
//Compute value for BRG register==========================================<br />
unsigned int time;<br />
time = ((TMR3+0x40)>>7)-1; //+0x40 for rounding<br />
//========================================================================<br />
return time;<br />
}<br />
*For 30MIP, tested speeds of transmission include 9600bps, 19200bps, 28800bps, 38400bps and 57600bps.<br />
====open()====<br />
*The following structures and variables are used as circular buffers for transmit and receive.<br />
struct UART_Rx{<br />
unsigned char wr;<br />
unsigned char rd;<br />
};<br />
struct UART_Tx{<br />
unsigned char wr; <br />
unsigned char rd;<br />
unsigned char tx_complete_flag;<br />
};<br />
struct UART_Rx uart_rx;<br />
struct UART_Tx uart_tx;<br />
unsigned char uart_rx_buf[MAX_UART_RX_BUF];<br />
unsigned char uart_tx_buf[MAX_UART_TX_BUF];<br />
<br />
char uart_open()<br />
{<br />
uart_rx.wr = 0;<br />
uart_rx.rd = 0;<br />
uart_tx.wr = 0;<br />
uart_tx.rd = 0;<br />
uart_tx.tx_complete_flag = 1;<br />
uart2_init();<br />
return 0;<br />
}<br />
<br />
void uart2_init(void){<br />
unsigned int u2brg = 97; <br />
#if(AUTO_BAUD_DECT>0)<br />
u2brg = uart2_autobaud();<br />
#endif<br />
U2BRG = u2brg; <br />
//=================================================================<br />
// Disable U2ART<br />
U2MODEbits.UARTEN = 0; //Disable U2ART module<br />
//=================================================================<br />
// Configure Interrupt Priority<br />
_U2RXIF = 0; //Clear Rx interrupt flags<br />
_U2TXIF = 0; //Clear Tx interrupt flags<br />
_U2RXIE = 1; //Receive interrupt: 0 disable, 1 enable <br />
_U2TXIE = 1; //Transmit interrupt: 0 disable, 1 enable<br />
//=================================================================<br />
// Configure Mode<br />
// +--Default: 8N1, no loopback, no wake in sleep mode, continue in idle mode<br />
// +--Diable autobaud detect<br />
// +--Enable U2ART module<br />
U2MODEbits.ABAUD = 0; //Disable Autobaud detect from U2RX <br />
U2MODEbits.UARTEN = 1; //U2ART enable<br />
//=================================================================<br />
// Configure Status<br />
// +--Default: TxInt when a char is transmitted, no break char<br />
// +--Default: RxInt when a char is received, no address detect, clear overflow<br />
// +--Enable Transmit<br />
U2STAbits.UTXEN = 1; //Tx enable<br />
}<br />
<br />
====write()====<br />
*This function writes a series of bytes to the circular buffer and start transmission.<br />
int uart_write(unsigned char *buf, int count)<br />
{<br />
//If transimt has not completed, return busy<br />
if(uart_tx.tx_complete_flag == 0){<br />
return -1; <br />
}<br />
else{<br />
uart_tx.tx_complete_flag = 0;<br />
}<br />
int next_data_pos;<br />
int byte = 0;<br />
for (; byte<count; byte++) {<br />
next_data_pos = pre_wr_cir254buf( (unsigned char)uart_tx.wr, <br />
(unsigned char)uart_tx.rd, <br />
MAX_UART_TX_BUF); <br />
if (next_data_pos!=255) {<br />
//Valid data is available<br />
uart_tx_buf[uart_tx.wr] = (unsigned char) buf[byte]; //copy the char to tx_buf<br />
uart_tx.wr = next_data_pos; //increment the ptr<br />
} else break;<br />
}<br />
//Raise Interrupt flag to initiate transmission<br />
_U2TXIF = 1; //Start interrupt<br />
return byte; <br />
}<br />
*The interrupt routine reads from the circular buffer and send the data. The uart is opened such that the module will generate an TX Interrupt when it a byte is sent.<br />
void _ISR _U2TXInterrupt(void){<br />
DISI_PROTECT(_U2TXIF = 0); //Clear Interrupt Flag<br />
unsigned char next_data_pos;<br />
next_data_pos = pre_rd_cir254buf( (unsigned char)uart_tx.wr,<br />
(unsigned char)uart_tx.rd, <br />
MAX_UART_TX_BUF);<br />
if (next_data_pos!= 255) {<br />
//Valid Data is available to transmit<br />
U2TXREG = (uart_tx_buf[(unsigned char)uart_tx.rd] & 0xFF); //send next byte...<br />
uart_tx.rd = (unsigned char) next_data_pos; //update rd pointer<br />
} else {<br />
//Transimission has completed<br />
uart_tx.tx_complete_flag = 1; // change to empty of tx<br />
}<br />
}<br />
<br />
====read()====<br />
*The interrupt routine writes to the circular buffer when space is available.<br />
void _ISR _U2RXInterrupt(void){<br />
unsigned char next_data_pos;<br />
if ( U2STAbits.URXDA ){<br />
next_data_pos = pre_wr_cir254buf( uart_rx.wr, uart_rx.rd, MAX_UART_RX_BUF);<br />
if (next_data_pos!=255) {<br />
//If buffer is not full<br />
uart_rx_buf[uart_rx.wr] = (unsigned char) U2RXREG; //Read the data from buffer<br />
uart_rx.wr = next_data_pos;<br />
} <br />
else{<br />
//When buffer is full, still remove data from register, butthe incoming data is lost<br />
next_data_pos = (unsigned char) U2RXREG; //Read the data from buffer<br />
} <br />
}<br />
DISI_PROTECT(_U2RXIF = 0); //Clear the flag<br />
}<br />
*This function reads one byte from the circular buffer.<br />
int uart_read(unsigned char *buf)<br />
{<br />
int next_data_pos;<br />
next_data_pos = pre_rd_cir254buf( uart_rx.wr, uart_rx.rd, MAX_UART_RX_BUF);<br />
//Copy 1 byte when data is available<br />
if (next_data_pos!=255) <br />
{<br />
*buf = uart_rx_buf[uart_rx.rd]; //copy the stored data to buf<br />
uart_rx.rd = next_data_pos; //update the ptr<br />
return 1;<br />
}<br />
//No data can be copied<br />
else<br />
{<br />
return 0;<br />
} <br />
}<br />
<br />
===I<sup>2</sup>C===<br />
<br />
----<br />
*Two lines are devoted for the serial communication. SCL for clock, SDA for data.<br />
*Standard communication speed includes<br />
#Standard speed mode: 100kHz<br />
#Fast speed mode: 400kHz<br />
#High speed mode: 3.4MHz<br />
*dsPIC30f5011 supports standard and fast speed modes. The maximum speed attainable is 1MHz.<br />
*Pull-up resistors are required for both SCL and SDA. Minimum pull-up resistance is given by:<br />
Pull-up resistor (min) = (V<sub>dd</sub>-0.4)/0.003 ...... [See section 21.8 in Family reference manual]<br />
*2.2Kohm is typical for standard speed mode.<br />
*After initiating a start/stop/restart bit, add a small delay (e.g. no operation) before polling the corresponding control bit (hardware controlled).<br />
*After sending a byte and receiving an acknowledgement from the slave device, ensure to change to idle state.<br />
<br />
====open()====<br />
*The following structure is used to record whether special bits are needed to be sent.<br />
typedef union{<br />
unsigned char val;<br />
struct{<br />
unsigned START:1; //start<br />
unsigned RESTART:1; //restart<br />
unsigned STOP:1; //stop<br />
unsigned NACK:1; //not acknowledgment<br />
unsigned :1;<br />
unsigned :1;<br />
unsigned :1;<br />
unsigned :1; <br />
}bits;<br />
} I2C_STATUS;<br />
static I2C_STATUS i2c_status; <br />
<br />
*Initializing I<sup>2</sup>C with default speed I2C_BRG without interrupts.<br />
void i2c_open(void)<br />
{<br />
//Open i2c if not already opened<br />
if(I2CCONbits.I2CEN == 0)<br />
{<br />
_SI2CIF = 0; //Clear Slave interrupt<br />
_MI2CIF = 0; //Clear Master interrupt<br />
_SI2CIE = 0; //Disable Slave interrupt<br />
_MI2CIE = 0; //Disable Master interrupt<br />
I2CBRG = I2C_BRG;<br />
I2CCONbits.I2CEN = 1; //Enable I2C module <br />
i2cIdle(); //I2C bus at idle state, awaiting transimission<br />
i2c_status.val = 0; //clear status flags<br />
}<br />
}<br />
<br />
====ioctl()====<br />
*Use this function before read/write to append special bits before or after the data byte.<br />
char i2c_ioctl(unsigned char request, unsigned char* argp)<br />
{<br />
switch(request){<br />
case I2C_SET_STATUS:<br />
i2c_status.val = *argp;<br />
break;<br />
default:<br />
return -1; //request code not recognised <br />
}<br />
return 0;<br />
}<br />
<br />
====write()====<br />
*This function sends an 8-bit data using the I2C protocol.<br />
Mst/Slv _______ M ____M___ S M ________ <br />
SDA (Data) |S| data |A|S|<br />
|T| |C|T|<br />
|A|XXXXXXXX|K|P|<br />
*Use ioctl() to select whether a start/restart/stop bit is required.<br />
*If slave does not respond after ACK_TIMEOUT, the transmission is considered unsucessful.<br />
int i2c_write(unsigned char *buf)<br />
{<br />
unsigned int count = 0;<br />
if(i2c_status.bits.START)<br />
{<br />
I2CCONbits.SEN = 1; <br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.SEN); //Wait till Start sequence is completed<br />
}<br />
else if(i2c_status.bits.RESTART)<br />
{<br />
I2CCONbits.RSEN = 1; <br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.RSEN); //Wait till Start sequence is completed<br />
}<br />
I2CTRN = *buf; //Transmit register<br />
while(I2CSTATbits.TBF); //Wait for transmit buffer to empty<br />
while(I2CSTATbits.ACKSTAT){<br />
if(++count > ACK_TIMEOUT){<br />
//Slave did not acknowledge, byte did not transmit sucessfully, <br />
//send stop bit to reset i2c<br />
I2CCONbits.PEN = 1;<br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.PEN); //Wait till stop sequence is completed<br />
i2cIdle();<br />
return 0;<br />
}<br />
}<br />
i2cIdle();<br />
if(i2c_status.bits.STOP)<br />
{<br />
I2CCONbits.PEN = 1;<br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.PEN); //Wait till stop sequence is completed<br />
i2cIdle();<br />
}<br />
i2c_status.val = 0; //Clear status<br />
return 1;<br />
}<br />
<br />
====read()====<br />
*This function reads 1 byte from slave using the I2C protocol.<br />
Mst/Slv ____ ___S____ M M _____ <br />
SDA (Data) | data |A|S|<br />
| |C|T|<br />
|XXXXXXXX|K|P|<br />
*Use ioctl() to select whether an ACK/NACK and/or STOP bit is needed to be sent.<br />
int i2c_read(unsigned char *buf)<br />
{<br />
I2CCONbits.RCEN = 1; //Enable Receive<br />
while(I2CCONbits.RCEN);<br />
I2CSTATbits.I2COV = 0; //Clear receive overflow<br />
*buf = (unsigned char) I2CRCV; //Access the receive buffer<br />
I2CCONbits.ACKDT = (i2c_status.bits.NACK)? 1 : 0;<br />
I2CCONbits.ACKEN = 1; //Send Acknowledgement/Not Acknowledgement<br />
i2cIdle(); //I2C bus at idle state, awaiting transimission<br />
if(i2c_status.bits.STOP)<br />
{<br />
I2CCONbits.PEN = 1;<br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.PEN); //Wait till stop sequence is completed<br />
i2cIdle();<br />
}<br />
i2c_status.val = 0; //Clear status<br />
return 1;<br />
}<br />
<br />
====Example====<br />
Mst/Slv _______ M ___M___ M S ____M___ S M ___M___ M S ___S____ M ___S____ M M _____ <br />
SDA (Data) |S| | |A| |A|R| | |A| |A| |N|S|<br />
|T|address|W|C|channelA|C|E|address|R|C| Data H |C| Data L |A|T|<br />
|A|1001111|0|K|00010010|K|S|1001111|1|K|10101010|K|10XXXXXX|K|P|<br />
<br />
/*<br />
* Send start bit, slave address (Write Mode)<br />
*/ <br />
status = I2C_START;<br />
i2c_ioctl(I2C_SET_STATUS, &status);<br />
data = (unsigned char) I2C_SLAVE_ADDR;<br />
i2c_write(&data);<br />
/*<br />
* Send control byte: Channel select<br />
*/<br />
data = (unsigned char) ctrl_byte;<br />
i2c_write(&data);<br />
/*<br />
* Send restart bit, slave address (Read Mode)<br />
*/<br />
status = I2C_RESTART;<br />
i2c_ioctl(I2C_SET_STATUS, &status);<br />
data = (unsigned char) (I2C_SLAVE_ADDR|0x01);<br />
i2c_write(&data);<br />
/*<br />
* Receive High Byte with Acknowledgment<br />
*/<br />
i2c_read(&data);<br />
usr_data.high = (unsigned char) data;<br />
/*<br />
* Receive Low Byte with Not Acknowledgment and stop bit<br />
*/ <br />
status = I2C_NACK | I2C_STOP;<br />
i2c_ioctl(I2C_SET_STATUS, &status);<br />
i2c_read(&data);<br />
usr_data.low = (unsigned char) data;<br />
<br />
===ADC===<br />
<br />
----<br />
*12-bit ADC: (Max 16 Channels)<br />
*Allow a maximum of 2 sets of analog input multiplexer configurations, MUX A and MUX B (Normally use one only).<br />
*A maximum of 200kps of sampling rate when using auto sampling mode.<br />
====open()====<br />
*The following variables are required.<br />
unsigned int adc_buf[ADC_MAX_CH]; //Store most updated data<br />
volatile unsigned int* ADC16Ptr = &ADCBUF0; //Pointer to ADC register buffer, <br />
unsigned char adc_ch_select = 0; //Pointer to channel to be read from<br />
unsigned char adc_data_ready = 0; //Indicate if RAM data is ready for output<br />
*Configuration is highlighted below.<br />
**Interrupt: The ADC module will be set to interrupt when the specified channels are updated.<br />
**I/O: Set the corresponding TRISBX bits (digit i/o config) to input (i.e. = 1), and set corresponding bits in ADPCFG (analog config) to zero.<br />
**Scanning Mode: Scan mode is used. In this mode, the Sample and Hold (S/H) is switched between the channels specified by ADCSSL (Scan select register).<br />
**Reference Voltage for S/H: Only MUX A is used. By default, the negative reference voltage of the S/H is connected to V<sub>REF-</sub>.<br />
**Settings for ADC Operation: For 200kbps operation, the voltage references for the ADC voltage are connected to V<sub>REF+</sub> and V<sub>REF-</sub>. Scan input is enabled, and the module will generate an interrupt when all selected channels have been scanned.<br />
**Sampling Rate: T<sub>AD</sub> refers to the time unit for the ADC clock. To configure the ADC module at 200kbps, the minimum sampling time of 1T<sub>AD</sub> = 334ns is required. ADCS<5:0> in ADCON3 register is used to set the time, which is given by:<br />
ADCS<5:0> = 2(T<sub>AD</sub>/T<sub>CY</sub>)-1 <br />
= 2(334e-9/33.34e-9)-1 <br />
= 19<br />
<br />
char adc_open(int flags)<br />
{<br />
// Configure interrupt<br />
_ADIF = 0; //clear ADC interrupt flag<br />
_ADIE = 1; //enable adc interrupt<br />
// Configure analog i/o <br />
_TRISB0 = 1;<br />
_TRISB1 = 1; <br />
ADPCFG = 0xFFFC; //Enable AN0 (Vref+) and AN1 (Vref-)<br />
// Configure scan input channels <br />
ADCSSL = 0x0003; //0 => Skip, 1 => Scan<br />
// Configure CH0 Sample and Hold for 200kbps<br />
// +-- Use MUX A only<br />
// +-- Set CH0 S/H -ve to VRef-<br />
ADCHSbits.CH0NA = 0;<br />
// ADCCON3:<br />
// +--Auto Sample Time = 1TAD<br />
// +--A/D Conversion Clock Source = system clock<br />
// +--A/D Conversion Clock Select ADCS<5:0>= 2(TAD/TCY)-1<br />
// 200kbps(Sampling frequency)<br />
ADCON3bits.SAMC = ADC_ACQ_TIME; //1TAD for sampling time<br />
ADCON3bits.ADRC = 0; //Use system clock<br />
ADCON3bits.ADCS = ADC_ADCS; //each conversion requires 14TAD<br />
// ADCCON2:<br />
// +--Default: Use MUX A, No splitting of Buffer<br />
// +--Voltage Reference Configuration Vref+ and Vref-<br />
// +--Scan Input Selections<br />
// +--5 samples between interrupt<br />
ADCON2bits.VCFG = 3; //External Vref+, Vref-<br />
ADCON2bits.CSCNA = 1; //Scan input<br />
ADCON2bits.SMPI = 1; //take 2 samples (one sample per channel) per interrupt<br />
// ADCCON1:<br />
// +--Default: continue in idle mode, integer format<br />
// +--Enable ADC, Conversion Trigger Source Auto, Auto sampling on<br />
ADCON1bits.FORM = 0; //[0:integer]; [2 fractional]; [3 siged fractional]<br />
ADCON1bits.SSRC = 7; //auto covert, using internal clock source<br />
ADCON1bits.ASAM = 1; //auto setting of SAMP bit<br />
ADCON1bits.ADON = 1; //Turn on module<br />
return 0;<br />
}<br />
<br />
====read()====<br />
*16 registers (ADCBUF0 -ADCBUF15) are dedicated to store the ADC data between interrupts. However, the data in ADCBUFx does not necessarily correspond to the data taken for channel x. Since the lowest register will always be filled first, when some of the channels are not scanned (i.e. skipped), care must be taken. The following code checks the ADCSSL register for the current scanning channels and moves the data to the corresponding position in *adc_buf.<br />
void _ISR _ADCInterrupt(void){<br />
unsigned int channel = 0;<br />
unsigned int buffer = 0;<br />
for (; channel<ADC_MAX_CH; channel++)<br />
{<br />
if(select(channel)) //Check if channel has been selected<br />
{<br />
adc_buf[channel] = ADC16Ptr[buffer]; //Copy data to adc_buf<br />
buffer++;<br />
}<br />
}<br />
adc_data_ready = 1;<br />
DISI_PROTECT(_ADIF = 0); //Clear adc interrupt<br />
}<br />
<br />
static unsigned char select(unsigned char ch)<br />
{<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
if(ADCSSL & mask)<br />
return 1;<br />
return 0;<br />
}<br />
*User can read from the buffer at anytime to get the most updated analog values.<br />
int adc_read(unsigned int* buf, int count)<br />
{<br />
if(adc_data_ready == 1)<br />
{<br />
int num_channel = count/2; //number of channels to read<br />
unsigned char channel = adc_ch_select; //index for adc_buf<br />
int i = 0; //index for buf<br />
while(i<num_channel && channel<ADC_MAX_CH)<br />
{ <br />
//Loop only for specified number of channel or all channels <br />
buf[i++] = adc_buf[channel++]; //use data in local buffer<br />
while(select(channel)==0)<br />
{ //increment to next valid channel<br />
channel++; <br />
if(channel >= ADC_MAX_CH) break;<br />
}<br />
}<br />
return 2*i;<br />
}<br />
return -1;<br />
}<br />
<br />
====ioctl()====<br />
*This function is used to add or remove channels from the ADC scanning process.<br />
char adc_ioctl(unsigned char request, unsigned char* argp)<br />
{<br />
switch(request)<br />
{<br />
case ADC_ADD_CH:<br />
//ADD channels to current set==========================<br />
cli(); //Disable global interrupt<br />
if(select(argp[0]) == 0){ //If channel not in scan list<br />
adcAdd(argp[0]); //Add individual channel to scan list<br />
adc_data_ready = 0; //First data not ready yet, until interrupt occurs<br />
}<br />
adc_ch_select = argp[0]; //Select current channel for reading<br />
sti(); //Enable global interrupt<br />
break;<br />
case ADC_RM_CH:<br />
//REMOVE channels from current set==========================<br />
cli(); //Disable global interrupt<br />
if(select(argp[0])){ //If channel in scan list <br />
adcRm(argp[0]); //Remove individual channel<br />
adc_ch_select = 0; //Reset to AN0<br />
}<br />
sti(); //Enable global interrupt<br />
break;<br />
default:<br />
return -1; //request code not recognised <br />
}<br />
return 0;<br />
}<br />
*Channels may be added or removed by changing _TRISBX, ADPCFG, ADCSSL and ADCON2bits.SMPI.<br />
void adc_add_ch(unsigned char ch){<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
TRISB = TRISB | mask;<br />
ADCSSL = ADCSSL | mask; <br />
ADPCFG = ~ADCSSL;<br />
ADCON2bits.SMPI++; //take one more sample per interrupt<br />
}<br />
<br />
void adc_rm_ch(unsigned char ch){<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
ADPCFG = ADPCFG | mask;<br />
ADCSSL = ~ADPCFG;<br />
ADCON2bits.SMPI--; //take one less sample per interrupt<br />
}<br />
<br />
===EEPROM===<br />
<br />
----<br />
*5011 has 1024 bytes of EEPROM, readable and writable under normal voltage (5V).<br />
*To use, declare:<br />
unsigned char _EEDATA(2) eeData[1024]={ 0x00, 0x00, 0x00, 0x00, .... }<br />
unsigned int byte_pointer = 0;<br />
====lseek()====<br />
*This function moves the pointer to the desired position before a reading/writing operation is performed.<br />
int eeprom_lseek(int offset, unsigned char whence){<br />
byte_pointer = offset;<br />
return byte_pointer;<br />
}<br />
====read()====<br />
*This function read ''count'' bytes from the eeprom.<br />
int eeprom_read(unsigned char* buf, int count){<br />
int i=0;<br />
for(; i<count && byte_pointer < 1024; i++){<br />
readEEByte( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + byte_pointer, <br />
&buf[i]);<br />
byte_pointer++; //Update global pointer<br />
}<br />
return i; //read i bytes successful <br />
}<br />
*readEEByte() is implemented in assembly code as follows:<br />
.global _readEEByte<br />
_readEEByte:<br />
push TBLPAG ;w0 = base of eeData<br />
mov w0, TBLPAG ;w1 = offset for eeData in byte<br />
tblrdl.b [w1], [w2] ;w2 = pointer to user buffer<br />
pop TBLPAG<br />
return<br />
<br />
====write()====<br />
*This function write ''count'' bytes to eeprom.<br />
int eeprom_write(unsigned char* buf, int count){<br />
char isOddAddr = byte_pointer%2; //current address is odd<br />
char isOddByte = count%2; //number of bytes to write is odd<br />
//=================================================================<br />
unsigned int word_offset = byte_pointer>>1; //div by 2 and round down<br />
int max_write;<br />
max_write = (isOddAddr == 0 && isOddByte == 0) ? (count>>1) : (count>>1)+1;<br />
//=================================================================<br />
unsigned int word_data; //Store word to be written<br />
int byte_wr = 0; //number of bytes written, i.e buffer pointer<br />
int i = 0;<br />
//=================================================================<br />
for(; i<max_write && word_offset<512; i++, word_offset++){<br />
if(i==0 && isOddAddr){<br />
//First byte not used<br />
//============================================save first byte<br />
readEEByte( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + byte_pointer - 1,<br />
&word_data);<br />
//===========================================================<br />
word_data = ((unsigned int)buf[0] << 8) + (0xFF & word_data);<br />
byte_wr++; //Update buffer pointer<br />
byte_pointer++; //Update global pointer<br />
} else if(i==max_write-1 && ((isOddAddr && sOddByte==0)||(isOddAddr==0 && isOddByte))){<br />
//Last byte not used<br />
//=============================================save last byte<br />
readEEByte( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + byte_pointer + 1,<br />
&word_data);<br />
//============================================================<br />
word_data = (word_data << 8) + buf[byte_wr];<br />
byte_wr++; //Update buffer pointer<br />
byte_pointer++; //Update global pointer<br />
} else{<br />
//Both bytes valid<br />
word_data = ((unsigned int)buf[byte_wr+1] << 8) + buf[byte_wr];<br />
byte_wr+=2; //Update buffer pointer<br />
byte_pointer+=2; //Update global pointer<br />
}<br />
//==================================================================<br />
eraseEEWord( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + 2*word_offset);<br />
writeEEWord( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + 2*word_offset,<br />
&word_data);<br />
//==================================================================<br />
}<br />
return byte_wr; //No. of byte written<br />
}<br />
*eraseEEWord and writeEEWord are implemented in assembly.<br />
.global _eraseEEWord<br />
_eraseEEWord:<br />
push TBLPAG <br />
mov w0, NVMADRU ;w0 = base of eeData<br />
mov w1, NVMADR ;w1 = offset for eeData in word<br />
mov #0x4044, w0 <br />
mov w0, NVMCON ;Set to erase operation<br />
push SR ;Disable global interrupts<br />
mov #0x00E0, w0<br />
ior SR<br />
mov #0x55, w0 ;Write the KEY sequence<br />
mov w0, NVMKEY<br />
mov #0xAA, w0 <br />
mov w0, NVMKEY<br />
bset NVMCON, #15 ;Start the erase cycle, bit 15 = WR<br />
nop<br />
nop<br />
L1: btsc NVMCON, #15 ;while(NVMCONbits.WR)<br />
bra L1<br />
clr w0<br />
pop SR ;Enable global interrupts<br />
pop TBLPAG<br />
return<br />
<br />
.global _writeEEWord<br />
_writeEEWord:<br />
push TBLPAG ;w0 = base of eeData<br />
mov w0, TBLPAG ;w1 = offset for eeData in byte<br />
tblwtl [w2], [w1] ;w2 = pointer to user buffer<br />
mov #0x4004, w0 ;Set to write operation<br />
MOV w0, NVMCON<br />
push SR ;Disable global interrupts<br />
mov #0x00E0, w0<br />
ior SR<br />
mov #0x55, w0 ;Write the KEY sequence<br />
mov w0, NVMKEY<br />
mov #0xAA, w0 <br />
mov w0, NVMKEY<br />
bset NVMCON, #15 ;Start the erase cycle, bit 15 = WR<br />
nop<br />
nop<br />
L2: btsc NVMCON, #15 ;while(NVMCONbits.WR)<br />
bra L2<br />
clr w0<br />
pop SR ;Enable global interrupts<br />
pop TBLPAG<br />
return<br />
<br />
===Simple PWM (Output Compare Module)===<br />
<br />
----<br />
<br />
*The PWM module consists of 8 channels using the output compare module of dsPic.<br />
*These channels are locate at pin 46 (OC1), 49 (OC2), 50 (OC3), 51 (OC4), 52 (OC5), 53 (OC6), 54 (OC7), 55 (OC8). These pins are shared with port D.<br />
*The range of PWM freqeuencies obtainable is 2Hz to 15MHz (See Figure 6.3). Suggested range of operation is 2Hz to 120kHz. The relationship between resolution ''r'' and PWM frequency ''f''<sub>PWM</sub> is given by:<br />
f<sub>PWM</sub> = f<sub>CY</sub>/(Prescale*10<sup>rlog(2)</sup>)<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 6.3 Relationship of Resolution and PWM Frequency<br />
! Resolution (bit) !! Prescale=1 !! Prescale=8 !! Prescale=64 !! Prescale=256<br />
|- <br />
|1||15,000,000 ||1,875,000 ||234,375||58,594 <br />
|- <br />
|2||7,500,000 ||937,500 ||117,188 ||29,297 <br />
|- <br />
|3||3,750,000 ||468,750 ||58,594 ||14,648 <br />
|- <br />
|4||1,875,000 ||234,375 ||29,297 ||7,324 <br />
|- <br />
|5||937,500 ||117,188 ||14,648 ||3,662 <br />
|- <br />
|6||468,750 ||58,594 ||7,324 ||1,831 <br />
|- <br />
|7||234,375 ||29,297 ||3,662 ||916 <br />
|- <br />
|8||117,188 ||14,648 ||1,831||458 <br />
|- <br />
|9||58,594 ||7,324 ||916 ||229 <br />
|- <br />
|10||29,297 ||3,662 ||458 ||114 <br />
|- <br />
|11||14,648 ||1,831 ||229||57 <br />
|- <br />
|12||7,324 ||916 ||114 ||29 <br />
|- <br />
|13||3,662 ||458 ||57 ||14 <br />
|- <br />
|14||1,831 ||229 ||29 ||7 <br />
|- <br />
|15||916 ||114 ||14 ||4 <br />
|- <br />
|16||458 ||57 ||7 ||2 <br />
|-<br />
|}<br />
<br />
====open()====<br />
*A timer (either Timer 2 or 3) is needed to determine the pwm period. The following code uses timer 2 for all 8 channels.<br />
void pwm_open(void){<br />
OC1CON = 0; OC2CON = 0; //Disable all output compare modules<br />
OC3CON = 0; OC4CON = 0;<br />
OC5CON = 0; OC6CON = 0;<br />
OC7CON = 0; OC8CON = 0;<br />
//============================================================<br />
TMR2 = 0; // Clear register<br />
PR2 = 0xFFFF; // Set to Maximum<br />
//============================================================<br />
_T2IF = 0; // Clear interrupt flag<br />
_T2IE = 0 // Enable interrupts<br />
//============================================================<br />
T2CONbits.TCS = 0; // Use internal clock source<br />
T2CONbits.TCKPS = 0; // Prescale Select 1:1<br />
//============================================================<br />
T2CONbits.TON = 1; // Start the timer <br />
}<br />
<br />
====ioctl()====<br />
*User should select the channel and set the pwm period using the functions below before issuing the duty cycle:<br />
char pwm_ioctl(unsigned char request, unsigned long* argp){<br />
unsigned int value;<br />
unsigned char mask;<br />
switch(request){<br />
case PWM_SET_PERIOD:<br />
return setPeriodNPrescale(argp[0]);<br />
case PWM_SELECT_CH:<br />
pwm_channel = argp[0];<br />
mask = 0x01 << pwm_channel;<br />
pwm_status = pwm_status | mask;<br />
return 0;<br />
default:<br />
return -1;<br />
}<br />
}<br />
char setPeriodNPrescale(unsigned long value_ns){<br />
unsigned long ans;<br />
unsigned long long numerator = (unsigned long long)value_ns*SYSTEM_FREQ_MHZ;<br />
int index= -1;<br />
unsigned long denominator;<br />
//-------------------------------------------------<br />
do{<br />
denominator = (unsigned long)1000*pwm_prescale[++index];<br />
ans = (unsigned long)(((long double)numerator/denominator) + 0.5) - 1; //round to nearest int<br />
} while(ans > 0x0000FFFF && index < 3);<br />
//-------------------------------------------------<br />
if(ans > 0x0000FFFF)<br />
return -1;<br />
//-------------------------------------------------<br />
T2CONbits.TON = 0; // Turn off the timer<br />
T2CONbits.TCKPS = index; // Change prescale factor<br />
PR2 = (unsigned int) ans; // Set to Maximum<br />
T2CONbits.TON = 1; // Turn on the timer <br />
//-------------------------------------------------<br />
return 0;<br />
}<br />
<br />
====write()====<br />
*User can change the duty cycle using the following functions<br />
int pwm_write(unsigned long* buf){<br />
if((pwm_status & (0x01 << pwm_channel)) == 0){<br />
return -1; //Channel has not been enabled<br />
}<br />
switch(pwm_channel){<br />
case 0:<br />
OC1RS = calcDCycle(buf[0]); OC1R = OC1RS; <br />
OC1CONbits.OCM = 6; //Simple PWM, Fault pin disabled<br />
break;<br />
case 1:<br />
OC2RS = calcDCycle(buf[0]); OC2R = OC2RS; <br />
OC2CONbits.OCM = 6; //Simple PWM, Fault pin disabled<br />
break;<br />
...<br />
case 7:<br />
OC8RS = calcDCycle(buf[0]); OC8R = OC8RS; <br />
OC8CONbits.OCM = 6; //Simple PWM, Fault pin disabled<br />
break; <br />
default:<br />
return -1;<br />
}<br />
return 4;<br />
}<br />
unsigned int calcDCycle(unsigned long value_ns){<br />
unsigned long long numerator = (unsigned long long)value_ns*SYSTEM_FREQ_MHZ;<br />
unsigned int index = T2CONbits.TCKPS;<br />
unsigned long denominator = (unsigned long)1000*pwm_prescale[index];<br />
return (unsigned int)(((long double)numerator/denominator) + 0.5) - 1; //round to nearest int<br />
}<br />
<br />
====Propagration Delay====<br />
*PWM channels sharing the same timer will have their PWM signals synchronised (i.e. the HIGH state of the duty cycle are all triggered together).<br />
*To introduced delay to the PWM signals, the signal from selected channels may be made to pass through a series of inverters (e.g. 74HC14D). This adds propagation delay to the signal.<br />
*However, as propagration delay of logic gates depends on applied voltage, temperature and load capacitance, the accuracy is low and performance is poor. For accurate delay, delay lines may be used, but they are expensive.<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 6.4 Propagation Delay of [http://www.nxp.com/acrobat_download/datasheets/74HC_HCT14_3.pdf Philips 74HC14D]<sup>[1], [2]</sup><br />
! !! 3.3V !! !! !! 5.0V !! !!<br />
|- <br />
! Number of Gates !! A !! B !! C !! A !! B !! C<br />
|- <br />
| 2 <br />
| 21ns (10.5)|| 23ns (11.5)|| 22ns (11.0)<br />
| 15ns (7.5)|| 14ns (7.0)|| 14ns (7.0)<br />
|-<br />
| 4 <br />
| 45ns (11.3)|| 46ns (11.5)|| 46ns (11.5) <br />
| 30ns (7.5)|| 30ns (7.5)|| 30ns (7.5)<br />
|-<br />
| 6 <br />
| 69ns (11.5)|| 70ns (11.7)|| 72ns (12.0) <br />
| 45ns (7.5)|| 46ns (7.7)|| 47ns (7.8)<br />
|- <br />
|}<br />
[1] Data in specification for 4.5V: Typical 15ns, Maximum 25ns<br><br />
[2] Data in specification for 6.0V: Typical 12ns, Maximum 21ns<br />
<br />
===DSP Library===<br />
<br />
----<br />
*Library functions in <dsp.h> include the following categories: <br />
#Vector<br />
#Window<br />
#Matrix<br />
#Filtering<br />
#Transform<br />
#Control<br />
<br />
====Data Types====<br />
*Signed Fractional Value (1.15 data format)<br />
**Inputs and outputs of the dsp functions adopt 1.15 data format, which consumes 16 bits to represent values between -1 to 1-2<sup>-15</sup> inclusive.<br />
**Bit<15> is a signed bit, positive = 0, negative = 1.<br />
**Bit<14:0> are the exponent bits ''e''.<br />
**Positive value = 1 - 2<sup>-15</sup>*(32768 - ''e'')<br />
**Negative value = 0 - 2<sup>-15</sup>*(32768 - ''e'')<br />
*40-bit Accumulator operations (9.31 data format)<br />
**The dsp functions use the 40 bits accumalators during arithmatic calculations.<br />
**Bit<39:31> are signed bits, positive = 0x000, negative = 0x1FF.<br />
**Bit<30:0> are exponent bits.<br />
*IEEE Floating Point Values<br />
**Fractional values can be converted to Floating point values using: '''fo = Fract2Float(fr);''' for fr = [-1, 1-2<sup>-15</sup>]<br />
**Floating point values can be converted to Fractional values using: '''fr = Float2Fract(fo);''' or '''fr = Q15(fo);''' for fo = [-1, 1-2<sup>-15</sup>]<br />
**Float2Fract() is same as Q15(), except having saturation control. When +ve >= 1, answer = 2<sup>15</sup>-1 = 32767 (0x7FFF). When -ve < -1, answer = -2<sup>15</sup> = -32767 (0x8000)<br />
<br />
===Build-in Library===<br />
<br />
----<br />
*Some assembler operators can only be accessed by inline assembly code, for example, <br />
#Manuipulation of accumulators A and B (add, sub, mul, divide, shift, clear, square)<br />
#Bit toggling<br />
#Access to psv (program space visiblity) page and offset<br />
#Access to table instruction page and offset<br />
*Built-in functions are written as C-like function calls to utilize these assembler operators.<br />
<br />
<br />
==Bootloader Development==<br />
<br />
===Concepts===<br />
*Programming with ICSP is useful when the target board is produced in batch. The producer can download a program even when the chip is on the target board.<br />
*However, ICSP requires an external programmer.<br />
*To allow the user to change the program after production but without the need of an external programmer, bootloader becomes useful.<br />
*Bootloader is a small program installed via ICSP. Everytime the device is reset, the bootloader is run first. The bootloader first detects the default serial channel whether the user wishes to download a new program to the device. If so, the bootloader will pause there, and wait for the user to download the hex file from the PC. The hex file is written to the device via RTSP instructions in the bootloader. If a new download is not necessary, the bootloader redirects to the previously installed user's program.<br />
*The disadvantage of bootloaders is that they consume some of the memory of the device.<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 7.1 Free bootloaders for dsPIC<br />
! Developer<br />
! Source<br />
! Platform<br />
! User Guide<br />
! Remarks<br />
|- valign="top"<br />
| [http://www.ingenia-cat.com/index.php?lang=en ingenia]<br />
| [http://www.ingenia-cat.com/download/iBL.s Assembly]<br />
| [http://www.ingenia-cat.com/download/ingeniadsPICbootloader1.1.zip Windows]<br />
| [http://www.ingenia-cat.com/reference/pdf/iBL.UG.V1.2.pdf pdf]<br />
| <br />
*Works for all dsPIC supporting RTSP<br />
*Auto baudrate detection<br />
*Use about 1.15% of the flash memory space (0xAFFF-0xAE00)/(0xAFFF-0x0100)<br />
*Development of Linux platform is underway<br />
*Modification of code for dsPIC30F5011 is successful<br />
|-valign="top"<br />
| [http://www.etc.ugal.ro/cchiculita/software/picbootloader.htm Tiny]<br />
| [http://www.etc.ugal.ro/cchiculita/software/tinybld191.zip Assembly]<br />
| Windows<br />
| [http://www.etc.ugal.ro/cchiculita/software/tinybldusage.htm Web]<br />
| <br />
*By default, only supports 601X, 601X, 401X, 2010<br />
*Smaller code size than ingenia, but not as easy to modify<br />
|-valign="top"<br />
| [http://www.via.si/software/dsPIC_bootloader/ Elektronika]<br />
| [http://www.via.si/software/dsPIC_bootloader/data/ Hex]<br />
| Windows<br />
| [http://www.via.si/software/dsPIC_bootloader/data/README.txt txt]<br />
| <br />
*Only works for dsPIC30F6014 serial port UART2 at baudrate 57600<br />
|-<br />
|}<br />
<br />
===dsPicBootloader===<br />
<br />
*The bootloader developed by ingenia is open source and it has been modified (see below) to suit our development using dsPic30f5011.<br />
*The bootloader (hereafter called dsPicBootloader) employs the following settings:<br />
# Use U2ART channel<br />
# Use FRC, PLL16<br />
# For 5011, the bootloader is located between 0x00AE00 to 0x00AFFE (512bytes). Refer to C:\Program Files\Ingenia\ingeniadsPICbootloader\ibl_dspiclist.xml after installing the GUI interface.<br />
*Changes made to [http://www.ingenia-cat.com/download/iBL.s assembly code] includes:<br />
1. including p30f5011.gld and p30f5011.inc<br />
.include "p30f5011.inc"<br />
2. changing the config code of UART #0x8420 -> #0x8020<br />
; Uart init<br />
mov '''#0x8020''', W0 ; W0 = 0x8020 -> 1000 0000 0010 0000b<br />
mov W0, U2MODE ; Enable UART, AutoBaud and 8N1<br />
clr U2STA<br />
3. changing the start address 0xAE00 - 0x0100 = 0AD00<br />
.equ CRC, W4<br />
.equ ACK, 0x55<br />
.equ NACK, 0xFF<br />
.equ USER_ADDRESS, 0x0100<br />
.equ START_ADDRESS, '''0xAD00''' ; Relative to 0x0100<br />
4. using Internal FRC and PLL16<br />
config __FOSC, CSW_FSCM_OFF & '''FRC_PLL16''' ;Turn off clock switching and<br />
;fail-safe clock monitoring and<br />
;use the Internal Clock as the<br />
;system clock<br />
5. disabling MCLR (optional)<br />
config __FBORPOR, PBOR_ON & BORV_27 & PWRT_16 & '''MCLR_DIS'''<br />
;Set Brown-out Reset voltage and<br />
;and set Power-up Timer to 16msecs<br />
6. changing all the related registers of U1ART to U2ART, all U1XXX => U2XXX<br />
'''U2MODE, U2STA, U2BRG, U2RXREG, U2TXREG'''<br />
7. changing all the related registers of IC1 to IC2, all IC1XXX => IC2XXX<br />
'''IC2CON, #IC2IF, #IC2IE'''<br />
<br />
===dsPicProgrammer (Java-based Multi-Platformed)===<br />
*Ingenia developed a programmer (PC-side) that works only in Windows environment. The project for Linux environment is currently suspended.<br />
*A simple programmer (hereafter called dsPicProgrammer) written in Java based on the library developed by [http://www.rxtx.org/ RXTX] has been developed here. The programmer supports both Linux and Windows environments, and may be used as a substitution for the official programmer developed by ingenia.<br />
*The programmer has the following specification and limitations:<br />
#Can be used on both Linux and Windows platforms.<br />
#Adjustable baudrate (9600bps to 57600bps<sup>[1]</sup>).<br />
#Support programming of dsPIC30F5011 and dsPIC33FJ128GP306<sup>[2]</sup> devices (Developers may add your devices).<br />
#Protection against overwriting bootloader codes on devices.<br />
#Detection if application program does not have its reset() at user's code start address.<br />
#Reprogramming can be done without powering down the target board, provided the user's program is compliant to that stated below.<br />
#Target board will run the user's program after programming is done.<br />
#Can be used with USB-Serial Cables. Below is a list of tested cable:<br />
::[http://www.prolific.com.tw/eng/Products.asp?ID=59 Prolific PL-2303 USB to Serial Bridge Controller]: [http://www.prolific.com.tw/eng/downloads.asp?ID=31 Driver download]<br />
'''NOTE:'''<br><br />
[1] from version 1.5.2 onwards, the baudrate is increased to 115200bps.<br><br />
[2] only dsPIC30 devices are compatible with the ingenia's programmer. For dsPIC33 devices, the protocol has been modified due to the increased flash size, and the dsPIC33 bootloader can only work with dsPicProgrammer.<br />
<br />
===Special Consideration===<br />
*The bootloader assumes that the user program starts at address 0x100. This is usually the case, but there are always exceptions.<br />
*To ensure that the user program always starts at address 0x100, you can create a customized linker script and customized reset() function as follows:<br />
:*Copy and modify the file named "crt0.s" from the directory "C:\Program Files\Microchip\MPLAB C30\src\pic30" to the project directory and include it.<br />
.section .reset, code //previously .section .libc, code <br />
:*Copy and modify the linkerscript for the device (e.g. p30f5011.gld) to the project directory and include it.<br />
.text __CODE_BASE :<br />
{<br />
*(.reset); //<-insert this line here<br />
*(.handle);<br />
*(.libc) *(.libm) *(.libdsp); /* keep together in this order */<br />
*(.lib*);<br />
*(.text);<br />
} >program<br />
<br />
===Communication Protocol===<br />
<br />
+-------------------+ +-------------------+----------------+<br />
| dsPicProgrammer | | dsPicBootloader | User's Program |<br />
+-------------------+ +-------------------+----------------+<br />
| PC | | Target dsPic |<br />
+-------------------+ +------------------------------------+<br />
| COM PORT |=============| UART |<br />
+-------------------+ +------------------------------------+<br />
<br />
* '''Stage 1: User's Configuation'''<br />
**Select a COM port channel<br />
**Select a baudrate<br />
**Select the user hex file<br />
java -jar dsPicProgrammer.jar COM1 19200 foo.hex<br />
* '''Stage 2: Resetting Target Device'''<br />
**dsPicProgrammer sends a Break character (pull UART-TX to low logic, which is normally high).<br />
**User's program on dsPic detects the break character and reset the chip<br />
::NOTE: The user's program is expected to have the following code in order to enable this function. Otherwise, the target board must be restarted manually.<br />
void _ISR _U2RXInterrupt(void)<br />
{<br />
//No Framming error<br />
if( U2STAbits.FERR == 0)<br />
{<br />
//Normal procedure<br />
}<br />
//Framming error<br />
else<br />
{<br />
if ( U2STAbits.URXDA ){<br />
unsigned char data;<br />
data = (unsigned char) U2RXREG;<br />
if(data == 0x00){<br />
// A break char has been received: <br />
// U2RX has been pulled to zero for more than 13 bits<br />
// This is used to reboot the pic<br />
mdelay(800); //wait for break character to clear<br />
asm("reset"); //software reset<br />
}<br />
} <br />
}<br />
_U2RXIF = 0; //Clear the flag<br />
}<br />
* '''Stage 3: Entering Ingenia's Protocol'''<br />
** Transmission is conducted in 8N1, i.e. 8-bit, no parity, 1 stop-bit<br />
** Communication Protocol is reviewed in [http://www.ingenia-cat.com/reference/pdf/iBL.UG.V1.2.pdf ingenia bootloader user's guide] section 2.1.3. The following summarises the key steps on the PC side (Refer also to section 2.2.2).<br />
::#Autobaud rate detection: dsPicProgrammer continuously sends a character "U" [0x55] via COM port and waits for an acknowledgment character "U", [ACK] = [0x55]<br />
::#Version Control: dsPicProgrammer sends the command character [0x03]. On success, dsPicProgrammer receives 3 characters i) Major Version ii) Minor Version iii) Acknowledgment [0x55]<br />
::#Device ID Monitoring: dsPicProgrammer sends the read command character [0x01] + 24-bit address [High][Medium][Low] (0xFF0000). Then, it receives 4-byte data [High][Medium][Low][ACK]<br />
::#Load the user hex file and check integrity<br />
::#Start Programming: dsPicProgrammer issues the write command character [0x02] + 24-bit address [High][Medium][Low]+ Number of bytes [N] + [data 0] + [data 1] + ... + [data N-1] + [CRC]=(INTEL HEX8 Checksum - Sum modulo 256) and receives [ACK] or [NACK] = [0xFF]<br />
::NOTE: Writing is in row mode access (i.e. erase and write a whole row, each row has 32 instructions, or 96 bytes because each instruction has 24 bits)<br />
* '''Stage 4: Goto User's Program'''<br />
**dsPicProgrammer sends the goto user code command [0x0F]<br />
<br />
<br />
==USB-RS232 Bridge==<br />
<br />
*As USB ports are becoming more and more common, COM ports and Parallel ports may be redundant in the next few years. This section explore the possibilities of programming the target board through a USB port.<br />
*There are two options:<br />
#Use an external USB/RS232 adaptor, the driver will emulate a virtual COM port, such as [http://www.prolific.com.tw/eng/downloads.asp?ID=31 Prolific] and [http://www.ftdichip.com/Drivers/VCP.htm FDTI]. Ingenia has tested its bootloader with some USB-232 manufacturers (silabs, FTDI, etc..). However, the programming failed with our Prolific adapter. Application program may use [http://java.sun.com/products/javacomm/ JavaComm API] (javax.comm) and/or [http://www.rxtx.org/ RXTX] to drive the COM port.<br />
#Modified the bootloader program on PC to support USB communication. e.g. using [http://jusb.sourceforge.net/ jUSB] and [http://javax-usb.org/ JSR-80] (javax.usb). External circuits such as PIC18F4550 and MAX232 are required.<br />
<br />
|--User's App.--|-------Device Manager------|-------USB-RS232 Interface------|---dsPIC---|<br />
Option 1:<br />
+-------------+ +----------+ +----------+ +---+ +------------+ +-----+ +--------+<br />
| Application |--| JavaComm |--| Virtual |==|USB|--| FDTI |--|RS232|==| Target |<br />
| Program | | RXTX | | COM Port | +---+ | Circuitary | +-----+ | Board |<br />
+-------------+ +----------+ +----------+ +------------+ +--------+<br />
Option 2:<br />
+-------------+ +--------+ +---+ +------------+ +-----+ +--------+<br />
| Application |----------| JSR-80 |==========|USB|--| PIC18F4550 |--|RS232|==| Target |<br />
| Program | | jUSB | +---+ | MAX232 | +-----+ | Board |<br />
+-------------+ +--------+ +------------+ +--------+<br />
<br />
*Currently, when RXTX is incorporated with JavaComm API, operating systems supported include Linux, Windows, Mac OS, Solaris and other operating systems. On the other hand, jUSB and JSR-80 only works for linux.<br />
<br />
===FDTI Chipset===<br />
*FT232RL communicates with PC via USB to provide 1 UART channel.<br />
*Datasheet can be downloaded [http://www.ftdichip.com/Documents/DataSheets/DS_FT232R.pdf here]. <br />
**Refer to Fig. 11 (Page 19) for Bus Powered Configuration.<br />
**Refer to Fig. 16 (Page 24) for for UART TTL-level Receive [RXD -> 1], Transmit [TXD -> 4], Transmit Enable [CBUS2/TXDEN -> 3]. Omit Receive Enable [CBUS3/PWREN#] and use [CBUS2/TXDEN -> 2] <br />
**Refer to Fig. 15 (Page 23) for LED Configuration: [CBUS0/TXLED#] and [CBUS1/RXLED#]<br />
*Virtual COM Port Drivers can be downloaded [http://www.ftdichip.com/Drivers/VCP.htm here].<br />
<br />
<br />
==Programming the Device==<br />
<br />
===Requirements===<br />
*Hardware<br />
#PC with COM port (Windows XP Installed for MPLAB)<br />
#ICD2 Programmer<br />
#Target Board<br />
#5V Power Supply<br />
<br />
*Software<br />
#[http://ww1.microchip.com/downloads/en/DeviceDoc/MP750.zip MPLAB IDE v7.50]: v7.60 is not compatible with our current [http://www.sure-electronics.com/ ICD2 Programmers]. There are consistent "Devices cannot be founded" warnings.<br />
#[http://chungyan5.no-ip.org/websvn/listing.php dsPicProgrammer] ('''dsPicProgrammer.jar''')<br />
#[http://users.frii.com/jarvi/rxtx/download.html RXTX driver]: download and upzip rxtx-2.1-7-bins-r2.zip (Final)<br />
<br />
*Files<br />
#[http://chungyan5.no-ip.org/websvn/listing.php dsPicBootloader] ('''bl_5011.hex'''). Original assembly code by ingenia can be downloaded from [http://www.ingenia-cat.com/download/iBL.s here].<br />
#Application hex file (e.g. '''app.hex''')<br />
<br />
===Loading Bootloader (Once only)===<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 9.1 Loading Bootloader<br />
! Step !! Remarks <br />
|-valign="top"<br />
| Install [http://ww1.microchip.com/downloads/en/DeviceDoc/MP750.zip MPLAB IDE] || <br />
*Do '''NOT''' connect ICD 2 (via USB) to PC<br />
*Execute '''MPLAB vX.XX Install.exe'''<br />
|-valign="top"<br />
| Install USB Driver ||<br />
*Follow the instruction in (C:\Program Files\Microchip\MPLAB IDE\ICD2\Drivers\Ddicd2.htm)<br />
|-valign="top"<br />
| Select Target Chip ||<br />
*Run MPLAB IDE on PC<br />
*Select: Configure>Select Devices...<br />
*Choose dsPIC30F5011<br />
|-valign="top"<br />
| Target <-> ICD 2 ||<br />
*Use six pin cable. Beware of the pin assignments. Only pin 1 - 5 should be used.<br />
*Place Jumper on target board (if any). The Jumper connects target V<sub>cc</sub> to ICD 2.<br />
*Do '''NOT''' power-up the target.<br />
|-valign="top"<br />
| ICD 2 <-> PC ||<br />
*Plug-in ICD 2 to PC via USB cable<br />
*Power-up the target.<br />
*Select: Programmer>Select Programmer>MPLAB ICD 2<br />
*If this is the first time the ICD 2 is connected to PC, MPLAB IDE will automatically download the required OS to ICD 2, wait until it has finished<br />
*If you have not connected and powered up the target, you might see Warnings on invalid device IDs, and/or running self tests.<br />
*See results of self test if necessary: Programmer>Settings, Status Tab. Refer to [http://ww1.microchip.com/downloads/en/DeviceDoc/51331B.pdf ICD2 User's Guide] Chapter 7.<br />
|-valign="top"<br />
| Load Bootloader ||<br />
*Select: File>Import...<br />
*Select '''bl_5011.hex'''<br />
|-valign="top"<br />
| Start Programming ||<br />
*Select: Programmer>Program<br />
|-valign="top"<br />
| Finishing ||<br />
*Power-down the Taget<br />
*Select: Programmer>Select Programmer>None<br />
*Unplug USB cable<br />
|-<br />
|}<br />
<br />
===Loading Firmware===<br />
<!--using Firefox-File-Page_Setup-Format-Scale-85% to print --><br />
====Java Environment Setup====<br />
*Download and install the latest JDK or JRE<br />
**Available from [http://java.sun.com/javase/downloads/index.jsp Sun Microsystems] (e.g. JDK 6 Update 3)<br>[[Image:1 1 java.JPG]]<br><br />
*Download and Extract RXTX Driver <br />
**Available from [http://users.frii.com/jarvi/rxtx/download.html RXTX] <br />
**File: rxtx-2.1-7-bins-r2.zip (Final)<br />
**Extract the files using software such as WinRAR<br>[[Image:1 2 rxtx.JPG]]<br><br />
*Copy RXTXcomm.jar<br />
**To C:\Program Files\Java\X\lib\ext (under the latest jre, e.g. X = jre1.6.0_03)<br>[[Image:1 3 rxtxcomm.JPG]]<br><br />
*Copy rxtxSerial.dll<br />
**To C:\Program Files\Java\X\bin (under the lastest jre, e.g. X = jre1.6.0_03)<br />
**For Linux users, copy librxtxSerial.so to /jre/lib/[machine type] (i386 for instance)<br>[[Image:1 4 rxtxserial.JPG]]<br><br />
*Download dsPicProgrammer <br />
**Available from [http://chungyan5.no-ip.org/vc here]<br />
**Expand the latest tag under dsPicProgrammer<br />
**File: dsPicProgrammer.jar<br>[[Image:1 5 dspicprogrammer.JPG]]<br><br />
**Save the file (dsPicProgrammer.jar) and your hex file (foo.hex) to your local directory (e.g. C:\dsPicProgrammer\)<br>[[Image:1 6 dspicprogrammer2.JPG]]<br><br />
=====directly download this [http://chungyan5.no-ip.org/open_data/electronic_computer/platforms/dspic/dsPicProgrammer/dsPicProgrammer1.5.2.zip package]=====<br />
<br />
====Download Firmware====<br />
*Start a Command Prompt<br />
**Start -> Run<br>[[Image:2 1 run.JPG]]<br><br />
**Enter cmd<br>[[Image:2 2 cmd.JPG]]<br><br />
*Run dsPicProgrammer<br />
**Make sure your device is connected through a "Direct RS232 Cable" to PC Serial Port. <br />
**Change to the directory where dsPicProgrammer.jar is located and run the command:<br />
***[path/to/java/]java -Djava.library.path=[path/to/rxtxlib] -jar dsPicProgrammer.jar COM1 57600 foo.hex<br />
****for example, jre\bin\java -Djava.library.path=.\rxtx\bin -jar dspicProgrammer.jar COM1 57600 foo.hex<br />
***Or directly using dsPicProgrammer.bat COM1 57600 foo.hex(Windows)<br />
***java -jar dsPicProgrammer.jar /dev/ttyS0 57600 foo.hex (Linux)<br />
:::where COM1 is your COM Port ID<br />
:::57600 is communication speed [in bps]<br />
:::foo.hex is your firmware new file<br />
::[[Image:2 3 command.JPG]]<br />
**When the program prompt you for an input, press y:<br>[[Image:2 4 prompt.JPG]]<br><br />
**If communication can be established, you should see something like this:<br>[[Image:2 5 progress.JPG]]<br><br />
**Wait until programming is completed.<br>[[Image:2 6 complete.JPG]]<br><br />
**after all completed, power OFF your device, then power ON again, enjoy your new updated.<br />
<br />
====Troubleshooting====<br />
*Invalid COM Port<br />
**In case of selecting an invalid COM port, you should see the error message:<br>gnu.io.NoSuchPortException: Choosing COM Port Error<br>[[Image:3 1 com err.JPG]]<br><br />
*Missing firmware file<br />
**In case of selecting a firmware file that does not exist, you should see the error message:<br>java.io.FileNotFoundException: foo1.hex <The system cannot find the file specified><br>[[Image:3 2 file err.JPG]]<br><br />
*Missing RXTX driver<br />
**In case of missing the RXTX driver, you should see the error message:<br>Exception in thread “main” java.lang.NoClassDefFoundError: gnu/io/UnsupportedCommOperationException<br>[[Image:3 3 rxtx err.JPG]]<br><br />
<br />
==Remote Access==<br />
*At the moment, local devices (e.g. EEPROM, ADC, DAC, etc.) can only be accessed locally through POSIX functions such as open(), read(), write(), ioctl().<br />
*However, a client may need to access these devices on a remote server. This section reviews the background and gives some ideas on its possible implementation.<br />
<br />
===Requirements===<br />
*A remote file access protocol, to transfer "files" (i.e. device's data) such as:<br />
#[http://en.wikipedia.org/wiki/FTP File Transfer Protocol] (FTP): Required files are copied from sever to client for manipulation<br />
#[http://en.wikipedia.org/wiki/Remote_Shell Remote Shell] (RSH): Required files are copied from sever to client for manipulation<br />
#[http://en.wikipedia.org/wiki/Network_File_System_%28Sun%29 Network File System] (NFS): Required files are manipulated on sever<br />
*An API to access files using a selected protocol, such as:<br />
#[http://www.die.net/doc/linux/man/man2/lam_rfposix.2.html lam_rfposix]: A POSIX-like remote file service for Local Area Multicomputer<br />
#API employed by VxWorks: [http://en.wikipedia.org/wiki/VxWorks VxWorks] is a Unix-like real-time operating system, commonly used for embedded systems.<br />
<br />
===API Reference for VxWorks===<br />
*Reference:<br />
**[http://www.windriver.com/vxworks/ VxWorks Official Website]<br />
**[http://www-cdfonline.fnal.gov/daq/commercial/ OS Libraries API Reference]<br />
*Related Libraies<br />
**netDrv (netDrv.h): an API using FTP or RSH<br />
**nfsDrv (nfsDrv.h): an API using NFS<br />
<br />
<br />
==Conversion to dsPIC33F Devices==<br />
*This section discusses the conversion required from dsPIC30F5011 to dsPIC33FJ128GP306.<br />
*Refer to official document [http://ww1.microchip.com/downloads/en/DeviceDoc/70172A.pdf dsPIC30F to dsPIC33F Conversion Guidelines] (DS70172A).<br />
*Note that this section does not mainly intend to introduce the new functionalities of dsPIC33F devices. It only serves the purpose to summarise the major (if not minimum) changes required to port the setup of dsPIC30 to dsPIC33 devices.<br />
<br />
===Hardware===<br />
*dsPIC33 operates at voltage of 3.3V. A voltage regulator, such as [http://www.national.com/ds.cgi/LM/LM3940.pdf LM3940] can be used to convert 5V supply to 3.3V.<br />
*A 1uF capacitor has to be placed at pin 56 (previously V<sub>SS</sub>, now V<sub>DDCORE</sub>).<br />
<br />
===Software===<br />
<br />
====Configuration Bits====<br />
<br />
----<br />
*dsPIC33 can operate at 40MIPs at maximum. To configure the device using internal FRC, replace the configuration bits setting as follows:<br />
_FOSCSEL(FNOSC_FRCPLL); // FRC Oscillator with PLL<br />
_FOSC(FCKSM_CSDCMD & OSCIOFNC_ON & POSCMD_NONE); <br />
// Clock Switching and Fail Safe Clock Monitor is disabled<br />
// OSC2 Pin Function: OSC2(RC15) as Digital IO<br />
// Primary Oscillator Mode: Disabled<br />
_FWDT(FWDTEN_OFF); // Watchdog Timer Enabled/disabled by user software <br />
*Configure on-chip PLL at runtime as follows (at start of main function):<br />
_PLLDIV = 38; // M=40: PLL Feedback Divisor bits<br />
CLKDIV = 0; // N1=2: PLL VCO Output Divider Select bits<br />
// N2=2: PLL Phase Detector Input Divider bits<br />
OSCTUN = 22; // Tune FRC oscillator, if FRC is used; <br />
// 0: Center frequency (7.37 MHz nominal)<br />
// 22: +8.25% (7.98 MHz)<br />
RCONbits.SWDTEN = 0; // Disable Watch Dog Timer<br />
while(OSCCONbits.LOCK != 1); // Wait for PLL to lock<br />
<br />
====UART====<br />
<br />
----<br />
*No change is required.<br />
<br />
====I2C====<br />
<br />
----<br />
*dsPIC33 supports upto 2 I<sup>2</sup>C devices. As a result, replace all I<sup>2</sup>C related registers with xxI2Cyy to xxI2C'''1'''yy. For examples:<br />
_SI2C1IF = 0; //Clear Slave interrupt<br />
_MI2C1IF = 0; //Clear Master interrupt<br />
_SI2C1IE = 0; //Disable Slave interrupt<br />
_MI2C1IE = 0; //Disable Master interrupt<br />
I2C1BRG = I2C_BRG; // Configure Baud rate<br />
I2C1CONbits.I2CEN = 1;<br />
...<br />
etc.<br />
<br />
====ADC====<br />
<br />
----<br />
*The ADC in dsPic33 is significantly different from that in dsPic30. Specifically, ADC in dsPic33 uses DMA to buffer the adc data. Replace the open, interrupt routine, add and remove codes as follows:<br />
<br />
unsigned int adc_bufA[ADC_MAX_CH] __attribute__((space(dma),aligned(256)));<br />
unsigned int adc_bufB[ADC_MAX_CH] __attribute__((space(dma),aligned(256)));<br />
unsigned int* ADC16Ptr; //Pointer to ADC register buffer, <br />
unsigned char adc_ch_select = 0; //Pointer to channel to be read from<br />
unsigned char adc_data_ready = 0; //Indicate if RAM data is ready for output<br />
unsigned int which_dma = 0; //indicate which adc_buf to be used<br />
<br />
void adc_open(void)<br />
{<br />
// Configure interrupt<br />
_AD1IF = 0; //clear ADC interrupt flag<br />
_AD1IE = 0; //disable adc interrupt<br />
AD1CHSbits.CH0NA = 0;<br />
// Configure analog i/o <br />
_TRISB0 = 1;<br />
_TRISB1 = 1; <br />
AD1PCFG = 0xFFFC; //Enable AN0 (Vref+) and AN1 (Vref-)<br />
AD1PCFGH = 0xFFFF; //AN16-AN31: Disabled<br />
// Configure scan input channels <br />
AD1CSSL = 0x0003; //0 => Skip, 1 => Scan<br />
AD1CSSH = 0x0000; //Skipping AN16-AN31<br />
// ADCCON4:<br />
AD1CON4bits.DMABL = 0; // Each buffer contains 1 word<br />
// ADCCON3:<br />
AD1CON3bits.SAMC = 1; //1TAD for sampling time<br />
AD1CON3bits.ADRC = 0; //Use system clock<br />
AD1CON3bits.ADCS = ADC_ADCS; //each conversion requires 14TAD<br />
// ADCCON2:<br />
AD1CON2bits.VCFG = 3; //External Vref+, Vref-<br />
AD1CON2bits.CSCNA = 1; //Scan input<br />
AD1CON2bits.SMPI = 1; //2 channels are scanned<br />
// ADCCON1:<br />
AD1CON1bits.FORM = 0; //[0:integer]; [2 fractional]; [3 siged fractional]<br />
AD1CON1bits.SSRC = 7; //auto covert, using internal clock source<br />
AD1CON1bits.ASAM = 1; //auto setting of SAMP bit<br />
AD1CON1bits.AD12B = 1; //12-bit, 1-channel ADC operation<br />
AD1CON1bits.ADDMABM = 0; // DMA buffers are built in scatter/gather mode<br />
AD1CON1bits.ADON = 1; // Turn on the A/D converter<br />
// DMA0 Configuration:<br />
DMA0CONbits.AMODE = 2; // Configure DMA for Peripheral indirect mode<br />
DMA0CONbits.MODE = 2; // Configure DMA for Continuous Ping-Pong mode<br />
DMA0PAD=(int)&ADC1BUF0; <br />
DMA0CNT = 1; // generate dma interrupt every 2 samples <br />
// same as SMPI because only 1 dma buffer per channel <br />
DMA0REQ = 13; // Select ADC1 as DMA Request source<br />
DMA0STA = __builtin_dmaoffset(adc_bufA); <br />
DMA0STB = __builtin_dmaoffset(adc_bufB);<br />
_DMA0IF = 0; // Clear the DMA interrupt flag bit<br />
_DMA0IE = 1; // Set the DMA interrupt enable bit<br />
DMA0CONbits.CHEN=1; // Enable DMA<br />
}<br />
<br />
void _ISR _DMA0Interrupt(void)<br />
{<br />
ADC16Ptr = (which_dma == 0)? adc_bufA : adc_bufB; //Update pointer<br />
adc_data_ready = 1;<br />
which_dma ^= 1; //Next buffer to be used<br />
_DMA0IF = 0; //Clear the DMA0 Interrupt Flag<br />
}<br />
<br />
static void adcAdd(unsigned char ch){<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
TRISB = TRISB | mask;<br />
AD1CSSL = AD1CSSL | mask; <br />
AD1PCFG = ~AD1CSSL;<br />
AD1CON2bits.SMPI++; //take one more sample per interrupt<br />
DMA0CNT++; <br />
}<br />
<br />
static void adcRm(unsigned char ch){<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
AD1PCFG = AD1PCFG | mask;<br />
AD1CSSL = ~AD1PCFG;<br />
AD1CON2bits.SMPI--; //take one less sample per interrupt<br />
DMA0CNT--; <br />
}<br />
<br />
====EEPROM====<br />
<br />
----<br />
*There is no EEPROM in dsPIC33 devices. Please consider to use an external EEPROM using I<sup>2</sup>C communication.<br />
<br />
====Simple PWM====<br />
<br />
----<br />
*No change is required.<br />
<br />
===Memory Map for dsPIC33FJ128GP306===<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 11.1 Memory Location<br />
! Type !! Start Address !! End Address !! Size<br />
|-valign="top"<br />
| Flash || 0x000000 ||0x0157FF || 86K<sup>[1]</sup><br />
|-valign="top"<br />
| +--Flash: Reset Vector || 0x000000 ||0x000003 || 4<br />
|-valign="top"<br />
| +--Flash: Interrupt Vector Table || 0x000004 ||0x0000FF || 252<br />
|-valign="top"<br />
| +--Flash: Alternate Vector Table || 0x000104 ||0x0001FF || 252<br />
|-valign="top"<br />
| +--Flash: User Program || 0x000200 ||0x0157FF || 85.5K<br />
|-valign="top"<br />
| Programming Executive || 0x800000 || 0x800FFF || 4K<sup>[1]</sup><br />
|-valign="top"<br />
| Config Registers || 0xF80000 || 0xF80017 || 24<br />
|-valign="top"<br />
| Device ID (0xE5) || 0xFF0000 || 0xFF0003 || 4<br />
|-<br />
|}<br />
[1] Each address is 16-bit wide. Every two addresses correspond to a 24-bit instruction. Each even address contains 2 valid bytes; each odd address contains 1 valid byte plus 1 phathom byte.<br><br />
<br />
===Custom Linker Script to Maximize Space for Constant Data===<br />
*Constant data declared using keyword '''const''' will be stored in the .const section in the flash memory.<br />
*Normally, during compilation, the linker will assign these data after the program code (.text section).<br />
*Since .const is accessed by auto-psv function, to maximize the space for constant data (32kb), the .const section needs to be aligned at 0x80000 boundary.<br />
*This requires the following change in linker script:<br />
<br />
__CONST_BASE = 0x8000;<br />
<br />
.text __CODE_BASE :<br />
{<br />
*(.reset);<br />
*(.handle);<br />
*(.libc) *(.libm) *(.libdsp); /* keep together in this order */<br />
*(.lib*);<br />
/* *(.text); deleted to maximize space for const data */<br />
} >program<br />
<br />
.const __CONST_BASE :<br />
{<br />
*(.const);<br />
} >program<br />
<br />
*If your program is large, after this change in linker script, function calls may involve large jump in the memory map (>32kB). As a result, you may need to enable the large code and large memory model during compilation. In such case, use the following options in your build path:<br />
-mlarge-code -mlarge-data<br />
*Meanwhile, functions that are defined in the standard C libraries, but are replaced with your own implementations (e.g. I/O stubs: open(), read(), write(), lseek(), ioctl() etc.) may have the following linker error:<br />
/usr/pic30-elf/lib//libc-elf.a(fflush.eo)(.libc+0x3c): In function '.LM11':<br />
: Link Error: relocation truncated to fit: PC RELATIVE BRANCH _write<br />
/usr/pic30-elf/lib//libc-elf.a(fclose.eo)(.libc+0x42): In function '.LM18':<br />
: Link Error: relocation truncated to fit: PC RELATIVE BRANCH _close <br />
*To resolve the problem, you need to place the functions in the .libc section rather than in the .text section, like this:<br />
#define LIBC_CODE_LOC __attribute__ ( (section(".libc")))<br />
<br />
int LIBC_CODE_LOC open(const char *pathname, int flags){ ... }<br />
int LIBC_CODE_LOC close(int fd){ ... }<br />
int LIBC_CODE_LOC write(int fd, void* buf, int count) { ... }<br />
int LIBC_CODE_LOC read(int fd, void* buf, int count) { ... }<br />
int LIBC_CODE_LOC ioctl(int fd, int request, void* argp) { ... }<br />
int LIBC_CODE_LOC lseek(int fd, int offset, int whence) { ... }<br />
<br />
===dsPicBootloader and dsPicProgrammer===<br />
*RTSP for dsPIC33F is different from dsPIC30F.<br />
**Row size changes from 32 instructions (96bytes) to 64 instructions (192 bytes)<br />
**Erase operation changes from 1 row to 8 rows<br />
**No EEPROM<br />
*With regards to the above changes, dsPicBootloader and dsPicProgrammer has been modified. In particular, dsPicProgrammer can be used to program both dsPic30F and dsPic33F devices (Yet, dsPic33F is no longer compatible with Ingenia's programmer). You can easily add your devices to the source code.<br />
<br />
==Downloads==<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 12.1 Related software download links for dsPicBootloader and dsPicProgrammer<br />
! Program<br />
! Site 1<br />
! Site 2<br />
! Remarks<br />
|- valign="top"<br />
| JDK<br />
| [http://java.sun.com/javase/downloads/index.jsp website]<br />
| <br />
| Download latest JDK<br />
|- valign="top"<br />
| RXTX<br />
| [http://users.frii.com/jarvi/rxtx/download.html website]<br />
| <br />
| Download rxtx-2.1-7-bins-r2.zip or later<br />
|- valign="top"<br />
| dsPicBootloader<br />
| [http://chungyan5.no-ip.org/vc click]<br />
| [http://www.opencircuits.com/images/a/a7/DsPicBootloader_1_3_1.zip click (v1.3)]<br />
| Under "dsPicBootloader/", download bl_5011.s or bl_j128gp306.s<br />
|-valign="top"<br />
| dsPicProgrammer<br />
| [http://chungyan5.no-ip.org/vc click]<br />
| [http://www.opencircuits.com/images/9/9e/DsPicProgrammer_1_3_5.zip click (v1.3.5)]<br />
| Under "dsPicProgrammer/", dowload dsPicProgrammer.jar<br><br>Alternatively, if you want to compile yourself or modify the source code, download <br>all source files under "dsPicProgrammer/" '''plus''' RdFileIntelHex.java under <br>"IntelHexPaser/tags/0.02.00/".<br>You should also install RXTX on your local machine as recommended in the readme file.<br />
|- valign="top"<br />
| Ingenia's bootloader<br />
| [http://www.ingenia-cat.com/en/downloads.php website]<br />
| <br />
| Download original ingenia's bootloader<br />
|-<br />
|}<br />
<br />
==ToDo==<br />
*dspic gcc compiler for constant problem<br />
*add chip to stable voltage upon power failure or to detect low voltage, and generate interrupt for dsPic to execute shutdown routine (e.g. save important data to NVM, shutdown ethernet etc.)<br />
*program the bootloader into flash under linux platform</div>Yanhttp://www.opencircuits.com/index.php?title=Techniques&diff=15942Techniques2008-07-15T07:56:38Z<p>Yan: Software Design Tool - silkscreen info.</p>
<hr />
<div>There are a wide variety of techniques used in electronics.<br />
<br />
<br />
== Printed circuit board design/fabrication ==<br />
=== Overview ===<br />
=== Software Design ===<br />
See [[#Software_design_tools|Software Design Tools]] below.<br />
<br />
==== Step by Step by using Software Design Tool ====<br />
*Format and shape of PCB are conformed.<br />
*Via size and location are conformed.<br />
*Fixed location item are placed on suitable place.<br />
*A one-first PCB silk layout is made.<br />
*All item get enough clearance between them.<br />
*All vias get enough size to install them components.<br />
*Make sure no wrong footprint is created.<br />
*PCB is drew.<br />
*silkscreen adding the following:<br />
**version no.<br />
**organization name<br />
**board name<br />
*Netlist is ran and got a no error result.<br />
*DRC is ran and got a no error result.<br />
*Location of item is reasonable.<br />
*All items are put on to a hard copy of PCB.<br />
*Overall is checked.<br />
<br />
And then the Gerbers are sent to a [[PCB Manufacturers]].<br />
<br />
=== Manual Design ===<br />
Somepeople do this with layout on clear film or by directly drawing on a circuit board, of even by scratching, grinding.... For now let them google this.<br />
<br />
=== Homebrew fabrication ===<br />
* [http://www.electricstuff.co.uk/pcbs.html "How to make really really good homemade PCBs"] by Mike Harrison 2007<br />
* [[Toner Transfer]] -- This method involves laser printing your PCB design onto paper, then transferring toner onto copper-clad board.<br />
* [[Photoetching]] -- Exposure of PCB designs onto photosensitized copper-clad board.<br />
* [[Chemical Etchants]]<br />
* [http://groups.yahoo.com/group/pcb-gcode "Mechanically etching or milling PCBs. No chemicals!"] -- Use your CNC router/mill to make PC boards.<br />
<br />
=== Commercial PCB fabrication ===<br />
* [[Submitting PCB's for fabrication]] -- Common processes for submitting PCB's for fabrication.<br />
* [[PCB Manufacturers]]<br />
* [http://diydrones.com/profiles/blog/show?id=705844%3ABlogPost%3A30196 "PCB fabbing advice"] by Chris Anderson 2008<br />
<br />
== Circuit construction (Prototyping - Other than custom PCB) ==<br />
<br />
* [[Solderless protoboard]] ([http://en.wikipedia.org/wiki/Breadboard Wikipedia:Breadboard]) ([http://www.best-microcontroller-projects.com/prototyping.html a simple example with a small microcontroller])<br />
* [[Point-to-point]] ([http://en.wikipedia.org/wiki/Point-to-point_construction Wikipedia:Point-to-point construction])<br />
* [[Wirewrap]] ([http://en.wikipedia.org/wiki/Wire_wrap Wikipedia:Wire Wrap])<br />
* [[Dead bug style]] -- and a similar method, [http://ciphersbyritter.com/RADELECT/BREADBD/BREADBD.HTM "A Modern Breadboarding Technology: Insulating Pads Soldered to a Ground Plane"]<br />
* [[Manhattan style]]<br />
<br />
[[http://www.techlib.com/electronics/construction.html "Construction Ideas"]] has nice photographs of the above circuit construction techniques.<br />
<br />
* [[Stripboard]] (Veroboard): ([http://en.wikipedia.org/wiki/Stripboard Wikipedia:stripboard].)<br />
<br />
== Soldering techniques ==<br />
<br />
* [[Basic soldering]] -- How to use a soldering iron.<br />
* Surface Mount<br />
** [[Skillet reflow]]<br />
** [[Toaster oven reflow]]<br />
** [[Hot air soldering]]<br />
* [[Rework]] -- Techniques for fixing mistakes, or for adding new features to a board that ''almost'' does what you want.<br />
** [http://workmanship.nasa.gov/lib/insp/2%20books/links/sections/302_jumper%20wires.html official NASA recommendations for adding discrete wiring ("jumper wires") to PCBs]<br />
<br />
(Have you seen this [http://www.hackaday.com/2007/06/04/cnc-solder-paste-pick-n-place/ CNC solder paste/pick n place] ?)<br />
<br />
== [[Hardware tool]]s ==<br />
A directory of [[hardware tool]]s that you may find useful.<br />
<br />
== Software design tools ==<br />
<br />
Some people still build circuits without ever using any software tools.<br />
For complicated circuits, software design tools can save a lot of time.<br />
<br />
Here we list "suites" that combine schematic capture, component editor for the components used in schematic capture, circuit simulation, PCB layout, autorouter, and footprint editor for the footprints used in PCB layout.<br />
(Is there another place for listing stand-alone tools such as a [[switching regulator|switching power supply]] "wizard" and a RF analysis tool?)<br />
<br />
Quite often people mix-and-match tools -- using a schematic capture from one suite to generate pretty schematics and a netlist, then importing the netlist a third party Specctra autorouter, then importing the result into a PCB layout program from another suite for the final manual clean-up and design rule checking.<br />
<br />
In no particular order:<br />
<!-- Please use a valid license ie, BSD, GPL, Crippleware, Nagware, Shareware, Payware etc.. And specify platform. There's usually a lot of free win32 crippleware without sources makeing you victim of the design file hostage scenario. Also some packages are sub-packages to others, thus maybe no needing an entry of their own. --><br />
{| class="wikitable"<br />
|- <br />
! Name !! Platform !! License !! AutoRouter !! Comments<br />
|-<br />
| [http://www.liquidpcb.org/ Liquid PCB] || Linux, Win32 || GPL || no || [http://liquidpcb.wiki.sourceforge.net/ Liquid PCB wiki at SourceForge] Liquid PCB is a computer aided design application for designing printed circuit boards. You are not restricted to straight tracks and 45º angles, you can draw tracks any way you like. The tracks will move and bend as required to maintain your design rules. It is open source, and still in the Alpha stage.<br />
|-<br />
|[http://geda.seul.org/ [[gEDA]]] || Linux, *BSD || Free, OSS || autorouter || [http://geda.seul.org/wiki/ gEDA wiki] includes schematic and [http://sourceforge.net/projects/pcb/ PCB] for makeing [[gerber|gerbers]] etc...<br />
|-<br />
|[http://mccad.com/ McCAD EDS Lite] || MacOSX, Win32 || Free demo max 200 pin || autorouter || Free demo version available for download, 200 pin limit<br />
|-<br />
|[http://applefritter.com/replica McCAD EDS SE] || MacOSX, Win32 || "free"? || autorouter || Free with book, "Apple I Replica Creation". Supports 750 pins, 11"x17" sheet size, 6-8 data layers. <tangent>(any useful tips in this book for those who want to build a CPU from scratch?) <reply>No, there are not. The book is more entry-level. - Tom Owad</reply></tangent> <br />
|-<br />
|[http://www.freepcb.com/ FreePCB] || Win32 || GPL || can use [http://www.freerouting.net/ FreeRoute] || PCB Design Software<br />
|-<br />
|[http://tinycad.sourceforge.net/ TinyCAD] || Win32 || LGPL || n/a || Schematic Drawing Software <br />
|-<br />
|[http://kicad.sourceforge.net/ KiCad] || BSD, Linux, MacOSX, Win32 || GPL || autorouter || http://www.lis.inpg.fr/realise_au_lis/kicad/ EDA suite ; [http://kicad.sourceforge.net/wiki/ KiCad wiki]<br />
|-<br />
|[http://expresspcb.com/ Express SCH/PCB] || Win32 || Free use crippleware || ? || ExpressPCB's propietatary free schematic capture & PCB layout designer locking you to use ExpressPCB for manufacture explicitly. Manufacture in 3 business days of two boards for ~100 USD.<br />
|-<br />
|[http://altium.com/ Protel DXP] || Win32 || || autorouter || [http://techref.massmind.org/techref/app/protel.htm independent Protel users FAQ] <br />
|-<br />
|[http://cadsoftusa.com/ Eagle] [[Eagle Links]] || Win32, Linux || Free use crippleware || || ( Russ Hensel says>> ) I have been kicking around as a hobbyist for a while and Eagle seems to be the main hobbyist circuit/pcb cad program. It supports schematics and board layout with an auto-router. The free version can easily support 2 dual op amps with wide traces and a one sided board. There is quite a lot of info on the Internet and many projects supply eagle files. There is also a $125 non profit version supporting larger boards. It then gets expensive. Eagle is not really easy to learn: cut for it would be copy in almost any other program. It probably deserves a page or more of its own. ( << end RH ) <br>http://cadsoft.de/ <br>[http://www.sparkfun.com/tutorial/PCB/eagle-output-tutorial.htm Eagle tutorial from Sparkfun] <br>[http://www.makezine.com/blog/archive/2006/03/how_to_make_a_custom_library_p.html Eagle tutorial (makezine)] <br />
|-<br />
|[http://diptrace.com/ DipTrace] || || Crippleware || || 250-pin Freeware or Purchase more advanced versions<br />
|-<br />
|[http://winqcad.com/ WinQcad] || || Crippleware || || Demo with max 499 pins available for download <br />
|-<br />
|[http://www.hutson.co.nz/ Rimu Schematic and Rimu PCB] || Win32 || Payware || || Schematic & PCB design for MS-Windows<br />
|-<br />
|[http://mentala.com/ SuperCAD and SuperPCB] || Win32 || || || Mental Automation schematic & PCB for MS-Windows<br />
|-<br />
|[http://www.autotraxeda.com/ autotraxeda.com] || || || || AUTOTraxEDA needs MS-NT, won't work on MS-W98/ME. User forums have shown a certain lack of satisfaction with the program.<br />
|-<br />
|[http://www.holophase.com/dleval.htm holophase.com/dleval] || Win32 || Crippleware || || Circad's DOS version is free for non-commercial use.<br />
|-<br />
|[http://www.geda.seul.org/ geda.seul.org] || BSD, Linux, MacOSX, Win32 || GPL || autorouter || xNIX Electronic Design Automation project has Schematic capture with PCB CAD.<br />
|-<br />
|[http://www.vutrax.co.uk/pricing.htm vutrax.co.uk/pricing] || Win32 || || autorouter || Vutrax for MS-Windows. Free for under 256 component pins.<br />
|-<br />
|[http://www.interactiv.com interactiv.com] || || || || Electronic Workbench, 400 USD for 500 pins. Includes schematic capture and simulation, virtual instruments and PCB layout. Said to be stable.<br />
|-<br />
|[http://pcb.sourceforge.net Harry Eaton's PCB] || BSD?, Linux?, MacOSX?, Win32 || GPL || autorouter || PCB design program which can work under any POSIX compliant operating system like Linux (or BSD under API compability layer). Have Gerber and PostScript output options.<br />
|-<br />
|[http://www.labcenter.co.uk/ labcenter.co.uk] || || || || They have a lite version "PIC bundle" ~149 USD includes schematic + simulation + pcb layout. You can write pic code for your pic schematic design and simulate. Even multi-pic, keypad, lcd display. Right now it can only simulate PIC16x83, PIC16x84 (lite version limited to 1k program code). Working on more pic modules. Will not produce Gerber or Excellion drill files. Only dxf, bmp, hpgl, tiff output (not sufficient!).<br />
|-<br />
|[http://www.ivex.com/ ivex.com] || || Payware || || Winboard PCB Layout, now [http://www.calcentron.com/Pages/NTEHomePage/ivex_cad_software.htm calcentron.com].<br />
|-<br />
|[http://www.illuminated.com.au/ illuminated.com.au] || Linux, Win32, DOS<!-- Claimed --> || || || Draftcad, Schematic Capture and PCB Design<br />
|-<br />
|[http://www.winqcad.com/ winqcad.com] || Win32, Linux+Wine || || || MicroCad<br />
|}<br />
<br />
(Some of this information in this table came from the [http://techref.massmind.org/techref/pcbcads.htm list of software design tools at the Massmind]).<br />
<br />
Is there any way to objectively compare these tools?<br />
How well did they do at the<br />
[http://www.pcbwest.com/topgun/ PCB Top Gun contest] ?<br />
<br />
== [[PC-Microcontroller Communications]] ==<br />
<br />
Discussion of the various methods to connect a microcontroller or embedded system to a PC.<br />
<br />
== Embedded System Programming and Testing ==<br />
To add to the confusion programming in embedded system can mean a person writing a program or a device called a programmer "burning" a program into a chip. This section is for the "burning" meaning of programming.<br />
<br />
* Many systems use [[JTAG]] for programming and testing. (Such as [http://en.wikibooks.org/wiki/Atmel_AVR Atmel AVR embedded systems]]).<br />
* Other systems use some other kind of in-circuit programming.<br />
* Some people use [http://en.wikibooks.org/wiki/Embedded_Systems/Bootloaders_and_Bootsectors bootloaders] to make re-programming a little quicker.<br />
<br />
-- not sure that this next one is not misplaced ? --<br />
''We're talking about "programming and testing" ? What else do you use to test op-amp circuits?''<br />
<br />
* Many people use an [[oscilloscope]] ([[o'scope]]). See [[oscilloscope]] for a list of Keith has made a list of low-cost o'scopesl [http://www.techtravels.org/amiga/amigablog/?p=167 "PC USB logic analyzers that cost under $1000."] for a list of low-cost logic analyzers.<br />
<br />
Humans writing a program almost always do it in a language. Here is a section that discusses some of these languages: [[Programming Languages]]<br />
<br />
== Enclosure ==<br />
<br />
* The Earth Signal should short to whole metal Case<br />
* Digital/Analog GND should separate to this Earth Signal, and should connect a Y-cap. to filter the noise between them.<br />
* Attention: do not place near between Earth Signal and Digital/Analog GND, otherwise some spark come out, and affect your whole system.<br />
<br />
== Further Reading ==<br />
<br />
* [http://airborn.com.au/method/ "Electronics Design" from Airborn] gives an overview of the complete process: specification, (schematic) circuit design, layout, prototypes, firmware, pilot run, production.<br />
* EDA electronic design automation software is a subset of CAD in general. Is there a wiki that discusses CAD in general? Until I find it, I'm going to post these tools here: "Google SketchUp is a powerful yet easy-to-learn 3D software tool" http://sketchup.google.com/ ; "Inkscape is the best tool for SVG standard vector graphics" http://wiki.inkscape.org/ ; Visual Wiki http://visualwiki.org/<br />
* [http://www.national.com/rap/Story/0,1562,18,00.html "What's All This Ground Noise Stuff, Anyhow?"] by Robert A. Pease<br />
* [http://www.elecdesign.com/Articles/ArticleID/6150/6150.html "What's All This Teflon Stuff, Anyhow?"] by Robert A. Pease -- explains a situation using lots of metal (instead of carefully insulating everything with lots of Teflon) causes less noise. Also mentions "why am I telling you all of these details? If I design a tester with greatly improved performance to help me test a really high-performance product, why should I tell all our competitors so that anybody in the world can test their products using the improved tester? Why should I give away all of these hard-earned secrets?" and gives some very good reasons.<br />
* [http://groups.google.to/group/sci.electronics.design/browse_thread/thread/889153f0e77b1718/fcaac532bb6d4b12?fwc=1 sci.electronics.design: EDN: Measuring Nanoamperes] discusses some ways to measure extremely small currents.<br />
* [http://www.millpcbs.com/ MillPCBs.com for techniques on using a small cnc machine to mill PCB's]<br />
* [http://groups.yahoo.com/group/Homebrew_PCBs yahoo.com/group/Homebrew_PCBs]<br />
* [http://www.electricstuff.co.uk/pcbs.html electricstuff.co.uk/pcbs]<br />
* [http://www.fullnet.com/~tomg/gooteepc.htm fullnet.com/~tomg/gooteepc]<br />
* The notion that through-hole soldering is easier than soldering surface-mount devices is, and always has been, [http://archives.seul.org/geda/user/Aug-2004/msg00175.html a myth.]<br />
* [http://www.instructables.com/id/Intro-into-SMD-Soldering/ Intro into SMD Soldering]<br />
* [http://PMinMO.com/ PMinMO.com is THE PLACE for DIY CNC driver information]<br />
<br />
== Environmental Issues ==<br />
<br />
see [[better for the environment]].<br />
<br />
<br />
[[Category:Techniques]]</div>Yanhttp://www.opencircuits.com/index.php?title=DsPIC30F_5011_Development_Board&diff=15797DsPIC30F 5011 Development Board2008-07-04T03:06:07Z<p>Yan: adding todo</p>
<hr />
<div>==Introduction==<br />
<br />
===Features of dsPIC30F5011===<br />
*2.5 to 5V <br />
*Up to 30MIPs<br />
*High current/sink source I/O pins: 25mA<br />
*DSP Instruction Set<br />
*Dual programming techniques: ICSP and RTSP<br />
*UART: up to 2 modules<br />
*I<sup>2</sup>C: up to 1Mbps<br />
*10-bit A/D, 1.1 Msps <br />
*12-bit A/D, 200 ksps<br />
*44K flash (66Kb), 4Kb RAM, 1Kb EEPROM<br />
*No DAC<br />
*Pin-to-pin compatible with other dsPICs<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 1.1 Comparison with Compatible dsPICs<br />
! dsPic !! Price<br>US$ !! MIPs<br />
! Flash<br>(kB)!! RAM<br>(kB) !! EEPROM<br>(kB)<br />
! I/O !! ADC<br>12-bit !! IC !! OC !! Motor<br>Ctrl !! Timers<br />
! QEI !! UART !! SPI !! I2C !! CAN !! Codec<br />
|- <br />
| 30F5011 || 5.91 || 30<br />
| 66 || 4 || 1<br />
| 52 || 16 || 8 || 8 || 0 || 5x16bit<br>2x32bit<br />
| 0 || 2 || 2 || 1 || 2 || 1<br />
|-<br />
| 30F6011A || 7.73 || 30<br />
| 132 || 6 || 2<br />
| 52 || 16 || 8 || 8 || 0 || 5x16bit<br>2x32bit<br />
| 0 || 2 || 2 || 1 || 2 || 0<br />
|-<br />
| 30F6012A || 7.85 || 30<br />
| 144 || 8 || 4<br />
| 52 || 16 || 8 || 8 || 0 || 5x16bit<br>2x32bit<br />
| 0 || 2 || 2 || 1 || 2 || 1<br />
|- <br />
| 33FJ128GP206 || 4.62 || 40<br />
| 128 || 8 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 1 || 0 || 1<br />
|-<br />
| 33FJ128GP306 || 4.81 || 40<br />
| 128 || 16 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 2 || 0 || 1<br />
|-<br />
| 33FJ128GP706 || 5.49 || 40<br />
| 128 || 16 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 2 || 2 || 1<br />
|-<br />
| 33FJ128MC506 || 4.97 || 40<br />
| 128 || 8 || 0<br />
| 53 || 16 || 8 || 8 || 8 || 9x16bit<br>4x32bit<br />
| 1 || 2 || 2 || 2 || 1 || 0<br />
|-<br />
| 33FJ128MC706 || 5.38 || 40<br />
| 128 || 16 || 0<br />
| 53 || 16 || 8 || 8 || 8 || 9x16bit<br>4x32bit<br />
| 1 || 2 || 2 || 2 || 1 || 0<br />
|-<br />
| 33FJ256GP506 || 6.11 || 40<br />
| 256 || 16 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 2 || 1 || 1<br />
|-<br />
|}<br />
<br />
===Web Page===<br />
*[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2529&param=en024856 Microchip Official Website]<br />
<br />
===Forum===<br />
*[http://direct.forum.microchip.com/default.aspx Microchip]: Official forum by Microchip<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=49 MPLAB ICD 2]: Subforum on ICD 2 programmer<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=57 MPLAB IDE]: Subforum on IDE<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=101 MPLAB C30 Compiler, ASM30, Link30 forum]: Subforum on C compiler. Refer to [http://ww1.microchip.com/downloads/en/DeviceDoc/C30_Users_Guide_51284e.pdf MPLAB C30 C Compiler User's Guide] Chapter 3<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=153 dsPIC30F Topics]: Subformum on dsPIC30F<br />
*[http://www.gnupic.org/ GNUPIC]: Discussion on PIC in Linux Systems<br />
**[http://www.linuxhacker.org/cgi-bin/ezmlm-cgi?1:dds:5443#b Debian]<br />
*[http://www.htsoft.com/forum/all/ubbthreads.php/Cat/0/C/6 HI-TECH Software Forum]: Discussion on dsPICC, a C compiler developed by HI-TECH<br />
*[http://piclist.com/techref/piclist/index.htm PICList]: Discussion on older PIC systems (not dsPIC)<br />
*[http://groups.google.com/group/pickit-devel PicKit]: Discussion on PICkit/PICkit 2 programmers<br />
*[http://sourceforge.net/forum/forum.php?forum_id=382005 FreeRTOS Real Time Kernel]: Open Discussion and Support on FreeRTOS <br />
<br />
===References===<br />
*dsPIC30F<br />
**[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2574 dsPIC30F Family Reference Manual Sections]: Contains detailed descriptions on dsPIC30F register definitions and example codes<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80169E.pdf dsPIC30F Family Reference Manual Errata (Use with revision 70046B only)]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70116F.pdf dsPIC30F5011, dsPIC30F5013 Data Sheet]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80210e.pdf dsPIC30F5011/5013 Rev. A1/A2 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80223D.pdf dsPIC30F5011/5013 Rev. A3 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70102G.pdf Flash Programming Specification]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70157B.pdf dsPIC30F Programmer's Reference Manual]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80170a.pdf dsPIC30F Programmer's Reference Manual Errata (use with revision DS70030E only)]<br />
<br />
*dsPIC33F<br />
**[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2573 dsPIC33F Family Reference Manual Sections]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70165E.pdf dsPIC33F Family Data Sheet]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80279B.pdf dsPIC33F Rev. A2 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80306A.pdf dsPIC33FJXXXGPX06/X08/X10 Rev. A2 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70152C.pdf Flash Programming Specification]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70172A.pdf dsPIC30F to dsPIC33F Conversion Guidelines]<br />
*ICD2 Programmer<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/51331B.pdf ICD2 User's Guide] <br />
*MPLAB<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/51519B.pdf MPLAB IDE User's Guide]<br />
*C30 Compiler<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/C30_Users_Guide_51284e.pdf MPLAB C30 C Compiler User's Guide]: Contains commands for using pic30-elf-gcc <br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/16bit_Language_Tool_Libraries_51456c.pdf 16-bit Language Tools Libraries]: Contains summaries and examples of using DSP libraries, standard C libraries and device libraries<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/Asm30_Link_Util_51317e.pdf MPLAB ASM30, MPLAB LINK30 and Utilities User's Guide]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/51322d.pdf dsPIC30F Language Tools Quick Reference Card]<br />
<br />
===Code Examples===<br />
*[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1408 Microchip Example Codes for dsPic]<br />
<br />
<br />
==Programming Methods==<br />
*There are 2 programming methods: In-Circuit Serial Programming (ICSP) and Run-Time Self-Programming (RTSP)<br />
*ICSP allows the devices to be programmed after being placed in a circuit board.<br />
*RTSP allows the devices to be programmed when an embedded program is already in operation.<br />
<br />
===ICSP: External Programmer (ICD2)===<br />
*Two types of ICSP are available: '''ICSP''' and '''Enhanced ICSP'''. Both of them require setting MCLR# to V<sub>IHH</sub> (9V – 13.25V).<br />
*Standard ICSP<br />
**Use external programmer (e.g. MPLAB<sup>®</sup> ICD 2, MPLAB<sup>®</sup> PM3 or PRO MATE<sup>®</sup> II) only.<br />
**Required low-level programming to erase, program and verify the chip.<br />
**Slower, because codes are serially executed.<br />
**Program memory can be erased using ''Normal-Voltage'' (4.5 – 5.5V) or ''Low-Voltage'' (2.5V – 4.5V).<br />
<br />
*Enhanced ICSP<br />
**Use external programmer and '''Programming Executive''' (PE).<br />
**PE is stored in the on-chip memory.<br />
**PE allows faster programming.<br />
**PE can be downloaded to the chip by external programmer using the standard ICSP method.<br />
**PE contains a small command set to erase, program and verify the chip, avoiding the need of low-level programming.<br />
<br />
====Hardware Interface====<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.1 Pin Used by ICSP<br />
! Pin Label !! Function !! Pin Number<br />
|- <br />
| MCLR# || Programming Enable|| 7<br />
|-<br />
| V<sub>DD</sub> || Power Supply || 10, 26, 38, 57<br />
|-<br />
| V<sub>SS</sub> || Ground || 9, 25, 41, 56<br />
|- <br />
| PGC || Serial Clock || 17<br />
|-<br />
| PGD || Serial Data || 18<br />
|-<br />
|}<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.2 Available Programmers in the Market<br />
! Product Name<br />
! Interface with PC<br />
! Interface with Device<br />
! Price (US)<br />
! Postage (US)<br />
! Total (US)<br />
|- <br />
| [http://direct.www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en010046&part=DV164005 MPLAB<sup>®</sup> ICD 2]<br />
| USB or RS232<br />
| [http://www.microchip.com/Microchip.WWW.SecureSoftwareList/secsoftwaredownload.aspx?device=en010046&lang=en&ReturnURL=http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en010046&part=DV164005# 6-PIN RJ-12 connector]<br />
| $159.99<br />
| -<br />
| -<br />
|-<br />
| [http://www.etekronics.com/product_info.php?cPath=24&products_id=48 Full Speed USB Microchip ICD2<br> Debugger and Programmer]<br />
| USB<br />
| 6-PIN ICSP connector<br>6-PIN RJ-12 connector<br />
| $72.00<br />
| $12.00<br />
| $84.00<br />
|-<br />
| [http://www.etekronics.com/product_info.php?cPath=24&products_id=47 Mini Microchip Compatible ICD2<br> Debugger and Programmer]<br />
| RS232<br />
| 6-PIN ICSP connector<br>6-PIN RJ-12 connector<br />
| $45.00<br />
| $10.00<br />
| $55.00<br />
|-<br />
| [http://www.inexglobal.com/microcontroller.php ICDX30]<br />
| RS232<br />
| 6-pin RJ-11<br />
| $51.00<br />
| $47.46<br />
| $98.46<br />
|-<br />
| *[http://www.sure-electronics.net Clone Microchip ICD2] (Now Using)<br />
| USB<br />
| 6-pin flat cables<br />
| $30.00<br />
| $12.00<br />
| $42.00<br />
|-<br />
|}<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.3 DIY ICD 2 Programmer Circuit<br />
! Source !! Schematic !! PIC16F877A Bootloader<br />
|- <br />
| [http://membres.lycos.fr/silicium31/Electronique/PIC/FreeIcdEnglish.htm Patrick Touzet]<br />
| [http://membres.lycos.fr/silicium31/Electronique/PIC/ICD2%20V1.3.pdf Yes]<br />
| [http://membres.lycos.fr/silicium31/Electronique/PIC/ICD2_FW.zip HEX]<br />
|-<br />
| [http://www.nebadje.org/doku.php?id=neblab:icd2clone Nebadje]<br />
| [http://people.ee.ethz.ch/~jbiveron/nebadje/ICD2_DOC.pdf Yes]<br />
| [http://people.ee.ethz.ch/~jbiveron/nebadje/ICD2_FW.zip Zip]<br />
|-<br />
|}<br />
<br />
====Software Interface====<br />
*The program can be written and compiled in an Integrated Development Environment (IDE) using either Assembly or C. The complied codes are then loaded to the device through the external programmer.<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.4 Summary of IDE<br />
! Product Name !! Features !! OS !! Price (US$)<br />
|- <br />
| [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en019469&part=SW007002 MPLAB<sup>®</sup> IDE]<br />
| Assembler Only<br />
| Windows<br />
| Free<br />
|-<br />
| [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en010065&part=SW006012 MPLAB<sup>®</sup> C30]<br />
| Assembler and C-Compiler<br />
| Windows<br />
| $895.00 (Free student version<sup>1</sup>)<br />
|-<br />
| [http://linux.softpedia.com/get/Science-and-Engineering/Electronic-Design-Automation-EDA-/Piklab-8099.shtml Piklab 0.12.0]<br />
| Assembler and C-Compiler<br />
| Linux<br />
| Free<sup>2</sup><br />
|}<br />
# Full-featured for the first 60 days. After 60 days, some code optimization functions are disabled. The compiler will continue to function after 60 days, but code size may increase.<br />
# The current version supports external programmer ICD 2, but not yet tested.<br />
<br />
===RTSP: COM Port (Bootloader)===<br />
*RTSP works in normal voltage (MCLR# no need to raise to V<sub>IHH</sub>).<br />
*No literature has mentioned the incorporation of Programming Executive (PE). Presumably, since Enhanced ICSP needs to set MCLR# to V<sub>IHH</sub>, RTSP cannot use PE.<br />
*Refer to [http://www.opencircuits.com/DsPIC30F_5011_Development_Board#Bootloader_Development bootloader section].<br />
<br />
<br />
==IC Requirements==<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 3.1 IC Requirements<br />
! Part No. !! Description <br />
! Min Temp !! Max Temp !! Min Volt !! Max Volt !! Typ Cur !! Max Cur<br />
|-valign="top"<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/70116F.pdf dsPIC30F5011-30I/PT] || uP <br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 2.5V <sup>[1]</sup>|| 5.5V<br />
| 145mA || 217mA<br />
|-<br />
| [http://datasheets.maxim-ic.com/en/ds/MAX3222-MAX3241.pdf MAX3232ESE] || RS232 driver<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 3.0V || 5.5V<br />
| 0.3mA || 1.0mA<br />
|-<br />
| [http://www.national.com/ds.cgi/DS/DS3695.pdf DS3695N] || RS485 driver<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 4.75V || 5.25V<br />
| 42mA || 60mA<br />
|-<br />
| [http://focus.ti.com/lit/ds/symlink/dac6574.pdf DAC6574IDGS] || 10-bit Quad-DAC I<sup>2</sup>C<br />
| -40<sup>o</sup>C || 105<sup>o</sup>C<br />
| 2.7V || 5.5V<br />
| 0.6mA || 0.9mA<br />
|-<br />
| [http://www.semiconductors.philips.com/acrobat/datasheets/74HC_HCT14_3.pdf 74HC14D] || Quad-Schmitt Trigger<br />
| -40<sup>o</sup>C || 125<sup>o</sup>C<br />
| 2.0V || 6.0V<br />
| || 0.02mA<br />
|-<br />
| '''Overall''' || <br />
| '''-40<sup>o</sup>C''' || '''85<sup>o</sup>C'''<br />
| '''4.75V''' || '''5.25V'''<br />
| || '''<300mA <sup>[2]</sup>'''<br />
|-<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/70165E.pdf dsPIC33FJ128GP306-I/PT] || uP <br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 3.0V <sup>[1]</sup>|| 3.6V<br />
| 74mA || 250mA<br />
|-<br />
| [http://www.analog.com/UploadedFiles/Data_Sheets/ADM3485E.pdf ADM3485EARZ] || RS485 driver<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 3.0V || 3.6V<br />
| 1.1mA || 2.2mA<br />
|-<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/21203N.pdf 24LC256-I/SN] || 256kBits I2C EEPROM<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 2.5V || 5.5V<br />
| 400uA || 3mA<br />
|-<br />
| [http://www.national.com/ds.cgi/LM/LM3940.pdf LM3940IMP-3.3] || 5V-3.3V Regulator<br />
| -40<sup>o</sup>C || 125<sup>o</sup>C<br />
| 5.0V || 7.5V<br />
| 10mA || 250mA<br />
|-<br />
|}<br />
#Minimum voltage measured is 3.3V (with 2 LEDs blinking) running at 30MHz.<br />
#Measured current at 5V is 180mA (with 2 LEDs blinking only)<br />
<br />
<br />
==Development Environment==<br />
<br />
===Windows===<br />
<br />
[[Image:PIC_setup_win.JPG]]<br />
<br />
*C-Compiler, Assembler and Linker are under GNU license.<br />
**MPLAB C30 C Compiler (*.c -> *.s)<br />
**MPLAB ASM30 Assembler (*.s -> *.o)<br />
**MPLAB LINK30 Linker (*.o -> *.bin)<br />
<br />
*PA optimizer, simulator, runtime libraries, header files, include files, and linker scripts are not covered by GNU. Reference is [http://direct.forum.microchip.com/tm.aspx?m=107208 here].<br />
<br />
*Microchip has integrated ASM30, LINK30, assembly header files, linker scripts in MPLAB IDE, which is free for download.<br />
*MPLAB C30 costs US$895. A 60-day free student version is also available. After 60-days, the optimizer is automatically disabled, while other tools can still function properly. Refer to Table 2.4.<br />
<br />
*C-libraries contained in C30 includes (Refer to [http://ww1.microchip.com/downloads/en/DeviceDoc/16bit_Language_Tool_Libraries_51456c.pdf 16-Bit Language Tools Libraries] from Microchip).<br />
<br />
<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 4.1 C Libraries in MPLAB C30<br />
! Library !! Directory <br>(\\Microchip\MPLAB C30) !! Major functions<br />
|-valign="top"<br />
| DSP Library <br>(e.g. libdsp-coff.a)<br />
| \lib <br> \src\dsp <br> \support\h<br />
| Vector, Matrix, Filter, etc.<br />
|-valign="top"<br />
| 16-Bit Peripheral Libraries <br>(e.g. libp30F5011-coff.a)<br />
| \lib <br> \src\peripheral <br> \support\h<br />
| ADC12, IOPort, UART, I<sup>2</sup>C, etc.<br />
|-valign="top"<br />
| Standard C Libraries <br>(e.g. libc-coff.a, libm-coff.a, libpic-coff.a)<br />
| \lib <br> \src\libm <br> \include<br />
| stdio.h, time.h, float.h, math.h, <br />
|-valign="top"<br />
| MPLAB C30 Built-in Functions<br />
| none<br />
| _buildin_addab, _buildin_add, _buildinmpy, etc<br />
|-<br />
|}<br />
<br />
===Linux===<br />
<br />
[[Image:PIC_setup_linux.JPG]]<br />
<br />
*C Compiler, Assembler and Linker are under GNU license.<br />
**The code can be downloaded from Microchip at [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en023073 here].<br />
**Current MPLAB ASM30 Assembler: v2.04<br />
**Current MPLAB C30 Compiler: v2.04<br />
<br />
*[http://gcc.gnu.org/ml/gcc/2005-02/msg01144.html John Steele Scott] has made templates that can be readily used by Debian-based systems. <br />
*For v1.32, the necessary conversion to *.deb has been done already at [http://noel.feld.cvut.cz/dspic/ here].<br />
**Download '''pic30-1.32-debian.tar.bz2''' for Template v1.32.<br />
**Download '''pic30-binutils_1.32-1_i386.deb''' for the assember.<br />
**Download '''pic30-gcc_1.32-1_i386.deb''' for the compiler.<br />
*For v2.00<br />
**goto http://www.baycom.org/~tom/dspic/<br />
**download pic30-gcc-2.00-1.i386.rpm and pic30-binutils-2.00-1.i386.rpm<br />
**convert to deb files<br />
**install these two deb files<br />
*For v3.01, convert the Toolchain following instructions at [http://www.nabble.com/Debian-templates-for-dsPIC-build-toolchain-3.01-tf4308624.html here]<br />
**Pre-install these packages: dpkg-dev, debhelper, bison, flex, sysutils, gcc-3.3, fakeroot<br />
***cmd: '''sudo apt-get install dpkg-dev debhelper bison flex sysutils gcc-3.3 fakeroot'''<br />
**Download and unzip template: '''pic30-3.01.tar.bz2'''<br />
**Download assembler: '''mplabalc30v3_01_A.tar.gz'''. Save under /pic30-3.01/pic30-binutils-3.01/upstream/<br />
**Download c-compiler: '''mplabc30v3_01_A.tgz'''. Save under /pic30-3.01/pic30-gcc-3.01/upstream/<br />
**Install MPLAB_C30_v3_01-StudentEdition under Windows<br />
**Copy directories /include, /lib, /support, and /bin/c30_device.info to pic30-3.01/pic30-support-3.01/upstream/<br />
**Pack pic30-binutils into deb file<br />
***goto /pic30-3.01/pic30-binutils-3.01/<br />
***type cmd: '''dpkg-buildpackage -rfakeroot -b'''<br />
**Pack pic30-gcc-3.01 into deb file<br />
***goto /pic30-3.01/pic30-gcc-3.01/<br />
***type cmd: '''dpkg-buildpackage -rfakeroot -b'''<br />
**Pack pic30-gcc-3.01 into deb file<br />
***goto /pic30-3.01/pic30-support-3.01/<br />
***type cmd: '''dpkg-buildpackage -rfakeroot -b'''<br />
**install pic30-binutils_3.01-1_i386.deb<br />
***type cmd: '''sudo dpkg -i pic30-binutils_3.01-1_i386.deb'''<br />
**install pic30-gcc_3.01-1_i386.deb<br />
***type cmd: '''sudo dpkg -i pic30-gcc_3.01-1_i386.deb'''<br />
**install pic30-support_3.01-1_all.deb<br />
***type cmd: '''sudo dpkg -i pic30-support_3.01-1_all.deb'''<br />
*'''Important Note''': Only the compiler is free. The header files and library are owned by Microchip. <br />
**Thomas Sailer suggested to download the Student version of C30 compiler and then build the libraries without source code. A package template for Fedora system is available [http://www.baycom.org/~tom/dspic/ here].<br />
**Instructions for filling the upstream direction is available [http://forum.microchip.com/printable.aspx?m=139360 here].<br />
**Alteratively, [https://gna.org/projects/pic30-libc/ Stephan Walter] has started a project to develop C Runtime Library for dsPIC. <br />
***Current libraries in version 0.1.1 include: assert.h, cdefs.h, ctype.h, errno.h, inttypes.h, stdint.h, stdio.h, stdlib.h, string.h<br />
<br />
*Burning Program Codes to Target Board<br />
#Use 'dspicprg and dspicdmp' utilities developed by [http://homerreid.ath.cx/misc/dspicprg/ Homer Reid] to burn hex code (*.hex) to devices. See Reference [http://forum.microchip.com/tm.aspx?m=94243 here]. Through serial port only?<br />
#Use [http://piklab.sourceforge.net/ Piklab IDE]. Details on file format not known.<br />
#Use [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en019469&part=SW007002 MPLAB IDE] to burn hex code (*.hex) to devices.<br />
<br />
===Code Optimization===<br />
*Below is a comparsion between different optimization levels for the project including drivers for 2 projects.<br />
<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 4.2 Comparison between differnt optimization levels<br />
! Optimization !! Description !! Project 1<br>Code Size<br>(byte) !! Project 1<br>Data Usage<br>(byte) !! Project 2<br>Code Size<br>(byte) !! Project 2<br>Data Usage<br>(byte)<br />
|-valign="top"<br />
| O0 <br />
| No optimization<br>Fastest Compilation<br />
| 6222 (9%) || 178 (4%) || 26,037 (38%) || 710 (17%)<br />
|-valign="top"<br />
| O1 <br />
| Optimize<br> Tries to reduce code size and execution time.<br />
| 4473 (6%) || 178 (4%) || 22,290 (32%) || 710 (17%)<br />
|-valign="top"<br />
| O2 <br />
| Optimize even more<br> Performs nearly all supported optimizations <br>that do not involve a space-speed trade-off. <br>Increases both compilation time and the <br>performance of the generated code.<br />
| 4422 (6%) || 178 (4%) || 21,993 (32%) || 710 (17%)<br />
|-valign="top"<br />
| O3 <br />
| Optimize yet more. <br>O3 turns on all optimizations specified by O2 <br>and also turns on the inline-functions option.<br />
| 4485 (6%) || 178 (4%) || 22,176 (32%) || 710 (17%)<br />
|-valign="top"<br />
| Os <br />
| Optimize for size. <br>Os enables all O2 optimizations that do not <br>typically increase code size. It also performs <br>further optimizations designed to reduce code <br>size.<br />
| 4356 (6%) || 178 (4%) || 21,885 (32%) || 710 (17%)<br />
|-<br />
|}<br />
<br />
<br />
==Software Architecture==<br />
+--------+--------+--------+--------+--------+<br />
Application | Task 1 | Task 2 | Task 3 | Task 4 | Task 5 |<br />
+--------+--------+--------+--------+--------+<br />
| POSIX API |<br />
+-------------------+------------------------+<br />
OS | Coroutine | FreeRTOS Scheduler |<br />
+-------------------+------------------------+<br />
| Drivers |<br />
+------+-----+-----+--------+-------+--------+<br />
Hardware | UART | ADC | DAC | EEPROM | PWM | TIMERS | <br />
+------+-----+-----+--------+-------+--------+<br />
*Currently, operating system is based on [http://www.freertos.org/ FreeRTOS] incorporating coroutine developed by [http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html Simon Tatham]<br />
*Software Drivers are to be developed to allow users at Application Level to use the hardware (e.g. ADC, DAC, UART, EEPROM etc) through the OS.<br />
*The interface between the drivers and the OS is based on [http://www.die.net/doc/linux/man/man2/ POSIX standard] (e.g. open(), write(), read(), ioctl(), usleep() etc).<br />
*The most up-to-date development can be found at repository [http://chungyan5.no-ip.org/vc/?root=freertos_posix freertos_posix]<br />
<br />
<br />
==Programming Tips==<br />
<br />
===Memory Map for 5011===<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 6.1 Memory Location<br />
! Type !! Start Address !! End Address !! Size<br />
|-valign="top"<br />
| Flash || 0x000000 ||0x00AFFF || 44K<sup>[1]</sup><br />
|-valign="top"<br />
| +--Flash: Reset Vector || 0x000000 ||0x000003 || 4<br />
|-valign="top"<br />
| +--Flash: Interrupt Vector Table || 0x000004 ||0x00007F || 124<br />
|-valign="top"<br />
| +--Flash: Alternate Vector Table || 0x000084 ||0x0000FF || 124<br />
|-valign="top"<br />
| +--Flash: User Program || 0x000100 ||0x00AFFF || 43.7K<br />
|-valign="top"<br />
| EEPROM || 0x7FFC00 || 0x7FFFFF || 1K<sup>[2]</sup><br />
|-valign="top"<br />
| Programming Executive || 0x800000 || 0x8005BF || 1472<br />
|-valign="top"<br />
| Unit ID || 0x8005C0 || 0x8005FF || 64<br />
|-valign="top"<br />
| Config Registers || 0xF80000 || 0xF8000F || 16<br />
|-valign="top"<br />
| Device ID || 0xFF0000 || 0xFF0003 || 4<br />
|-<br />
|}<br />
[1] Each address is 16-bit wide. Every two addresses correspond to a 24-bit instruction. Each even address contains 2 valid bytes; each odd address contains 1 valid byte plus 1 phathom byte.<br><br />
[2] Each address is 8-bit wide.<br />
<br />
===Data Location===<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 6.2 Data Location<br />
! Type !! Description !! Example<br />
|-valign="top"<br />
| _XBSS(N) <sup>[1]</sup><br />
| RAM Data in X-memory, aligned at N, no initilization<br />
| int _XBSS(32) xbuf[16];<br />
|-valign="top"<br />
| _XDATA(N) <sup>[1]</sup><br />
| RAM Data in X-memory, aligned at N, with initilization<br />
| int _XDATA(32) xbuf[] = {1, 2, 3, 4, 5};<br />
|-valign="top"<br />
| _YBSS(N) <sup>[1]</sup><br />
| RAM Data in Y-memory, aligned at N, no initilization<br />
| int _YBSS(32) ybuf[16];<br />
|-valign="top"<br />
| _YDATA(N) <sup>[1]</sup><br />
| RAM Data in Y-memory, aligned at N, with initilization<br />
| int _YDATA(32) ybuf[16] = {1, 2, 3, 4, 5};<br />
|-valign="top"<br />
| __attribute__((space(const)))<br />
| Flash ROM data, constant, accessed by normal C<br>statements, but 32K max.<br />
| int i __attribute__((space(const))) = 10;<br />
|-valign="top"<br />
| __attribute__((space(prog)))<br />
| Flash ROM data, read/write by program space visibility<br>window (psv)<br />
| int i __attribute__((space(prog)));<br />
|-valign="top"<br />
| __attribute__((space(auto_psv)))<br />
| Flash ROM data, read by normal C statements, write<br>by accessing psv<br />
| int i __attribute__((space(auto_psv)));<br />
|-valign="top"<br />
| __attribute__((space(psv)))<br />
| Flash ROM data, read/write by (psv)<br />
| int i __attribute__((space(psv)));<br />
|-valign="top"<br />
| _EEDATA(N) <sup>[1]</sup><br />
| ROM Data in EEPROM, aligned at N, read/write with psv<br />
| int _EEDATA(2) table[]={0, 1, 2, 3, 5, 8};<br />
|-valign="top"<br />
| _PERSISTENT<br />
| RAM Data, data remain after reset<br />
| int _PERSISTENT var1, var2;<br />
|-valign="top"<br />
| _NEAR<br />
| RAM Data at near section<br />
| int _NEAR var1, var2;<br />
|-valign="top"<br />
| _ISR<br />
| Interrupt service rountine<br />
| void _ISR _INT0Interrupt(void);<br />
|-valign="top"<br />
| _ISRFAST<br />
| Fast interrupt service rountine<br />
| void _ISRFAST _T0Interrupt(void);<br />
|-<br />
|}<br />
#N must be a power of two, with a minimum value of 2.<br />
<br />
===Configuration Bits===<br />
----<br />
*System clock source can be provided by:<br />
#Primary oscillator (OSC1, OSC2)<br />
#Secondary oscillator (SOSCO and SOSCI) with 32kHz crystal<br />
#Internal Fast RC (FRC) oscillator at 7.37MHz (7372800Hz)<br />
#Low-Power RC (LPRC) oscillator (Watchdog Timer) at 512 kHz.<br />
*These clock sources can be incorporated with interal Phase-locked-loop (PLL) x4, x8 or x16 to yield the osciallator frequrence F<sub>OSC</sub><br />
*The system clock is divided by 4 to yield the internal instruction cycle clock, F<sub>CY</sub>=F<sub>OSC</sub>/4<br />
*FRC with PLLx16 is used to achieve F<sub>CY</sub>=29.49MHz (29491200Hz or 30MIPS)<br />
<br />
//The code (MACRO) below is to be placed at the top of program (before main)<br />
_FOSC(CSW_FSCM_OFF & FRC_PLL16);<br />
_FWDT(WDT_OFF); //Turn off Watchdog Timer<br />
_FBORPOR(PBOR_ON & BORV_27 & MCLR_DIS & PWRT_16);<br />
_FGS(CODE_PROT_OFF); //Disable Code Protection<br />
<br />
===Timer===<br />
<br />
----<br />
*Each timer is 16-bit (i.e. counting from 0 to 65535).<br />
*Timer 2 and 3 can be incorporated together to form a 32-bit timer.<br />
*Prescale is the ratio between timer counts and system clock counts. Prescales of 1:1, 1:8, 1:64 and 1:256 are available.<br />
*Timers may be used to implement free time clock or mesaure time.<br />
<br />
====Free Time Clock====<br />
*Let required time for ticking be PERIOD.<br />
*Number of instruction cycles during PERIOD = PERIOD*F<sub>CY</sub> cycles<br />
*Using a prescale of 1:x, the timer period count register = # of cycles/x<br />
*e.g. PERIOD = 10ms; # of cycles = 10ms*30MHz = 300000 cylces; Using 1:64 Prescale, register setting = 300000/64 = 4688<br />
void time_init(void){<br />
TMR1 = 0; // Clear register<br />
PR1 = 4688; // Set period<br />
//============================================================<br />
_T1IF = 0; // Clear interrupt flag<br />
_T1IE = 1; // Enable interrupts<br />
//============================================================<br />
T1CONbits.TCS = 0; // Use internal clock source<br />
T1CONbits.TCKPS = 2; // Prescale Select 1:64<br />
T1CONbits.TON = 1; // Start the timer <br />
}<br />
//********************************************************************<br />
void _ISRFAST _T1Interrupt(void){<br />
_T1IF = 0; // Clear interrupt flag<br />
//Place user code here<br />
}<br />
<br />
====Time Measurement====<br />
*To measure the time taken for action(), use the code below:<br />
unsigned int measure_time(void){ <br />
PR3 = 0xFFFF; // Set counter to maximum<br />
_T3IF = 0; // Clear interrupt flag<br />
_T3IE = 0; // Disable interrupt<br />
T3CONbits.TON = 1; // Start the timer, TMR3 count up<br />
TMR3 = 0; //Clear TMR3 to start count up<br />
//====================================================<br />
//Add code here to wait for something to happen<br />
action();<br />
//====================================================<br />
T3CONbits.TON = 0; //Stop the timer<br />
//====================================================<br />
return (unsigned int) TMR3/FCY; //TMR/FCY yields the actual time<br />
}<br />
<br />
===Interrupt===<br />
<br />
----<br />
*Registers are involved in Interrupts includes: <br />
#Interrupt Flag Status (IFS0-IFS2) registers<br />
#Interrupt Enable Control (IEC0-IEC2) registers<br />
#Interrupt Priority Control (IPC0-IPC10) registers<br />
#Interrupt Priority Level (IPL) register<br />
#Global Interrupt Control (INTCON1, INTCON2) registers<br />
#Interrupt vector (INTTREG) register<br />
*User may assign priority level 0-7 to a specific interrupt using IPC. Setting priority to 0 disable a specific interrupt. Level 7 interrupt has the highest priority.<br />
*Current priority level is stored in bit<7:5> of Status Register (SR). Setting Interrupt Priority Level (IPL) to 7 disables all interrupts (except traps). <br />
*sti() and cli() can be defined to enable and disable global interrupts for time critical functions:<br />
#define IPL ( 0x00e0 )<br />
#define cli() SR |= IPL //Set IPL to 7<br />
#define sti() SR &= ~IPL //Set IPL to 0<br />
//============================================================<br />
char adc_ioctl(unsigned char request, unsigned char* argp){<br />
//...<br />
cli(); //Disable global interrupt<br />
for(;ch<=argp[0];ch++)<br />
adc_add_ch(argp[ch]); //Add adc channels<br />
sti(); //Enable global interrupt<br />
//...<br />
return 0;<br />
}<br />
*dsPic30F has an [http://ww1.microchip.com/downloads/en/DeviceDoc/80223D.pdf errate note] on the Interrupt Controller. When Nested Interrupt is turned on (NSTDIS=0 by default), a high priority interrupt negating a low priority interrupt may result in an Address Error.<br />
*To work around the problem, it is suggested by Microchip to use the following MACRO to protect:<br />
# the clearing of Interrput Flag<br />
# the disabling of Interrupt Enable<br />
# the lowering of Interrupt Priority <br />
# the modification of IPL in Status Register to 1-6<br />
#define DISI_PROTECT(X) { \<br />
__asm__ volatile ("DISI #0x1FFF");\<br />
X; \<br />
DISICNT = 0; \<br />
}<br />
*For example,<br />
void _ISR _T1Interrupt( void )<br />
{<br />
DISI_PROTECT(IFS0bits.T1IF = 0);<br />
//do something here...<br />
}<br />
<br />
===UART===<br />
<br />
----<br />
*5011 provides two UART channels UxART, for x=1, 2.<br />
*UxMODE, UxSTA, UxBRG are registers used to set the mode, indicate the status, and set the baud rate respectively.<br />
*For UART communications compatiable with RS232 standard, an external driver (e.g. MAX3232ESE) is needed.<br />
*For UART communications compatiable with RS485 standard, an external driver (e.g. DS3695N) is needed.<br />
====Auto baud rate detection====<br />
*The method is provided by [http://www.opencircuits.com/DsPIC30F_5011_Development_Board ingenia bootloader].<br />
*The PC sends a ASCII character 'U' (0x55) to the target board.<br />
*On the first rising edge of the start bit, the target board starts the timer.<br />
*At the fifth rising edge, the timer is stopped, let the count number be ''t_count''. <br />
**The measured period corresponds to 8 bits transmitted at a baud rate ''uxbrg''.<br />
_ _ _ _ _ _<br />
_|S|_|1|_|1|_|1|_|1|_|S|_ (S = Start Bit)<br />
<---------------><br />
Measured Time<br />
*The relationship between ''uxbrg'' and ''TMR'' is<br />
Measured Time (in seconds) = t_count/F<sub>cy</sub><br />
uxbrg = 1/(Measured Time/8)<br />
= 8*F<sub>cy</sub>/t_count<br />
*Since UxBRG is computed by:<br />
UxBRG = (F<sub>cy</sub>/(16*Baudrate)) -1<br />
= (F<sub>cy</sub>/(16*8*F<sub>cy</sub>/t_count)) -1<br />
= t_count/128 -1<br />
*The following is the code for auto baud rate detection for U2ART:<br />
unsigned int uart2_autobaud(void){<br />
U2MODEbits.ABAUD = 1; //Enable Autobaud detect from U2RX (from IC2 if 0)<br />
U2MODEbits.UARTEN = 1; //U2ART enable<br />
//Timer 3 Config==========================================================<br />
PR3 = 0xFFFF; // Set counter to maximum<br />
_T3IF = 0; // Clear interrupt flag<br />
_T3IE = 0; // Disable interrupt<br />
T3CONbits.TON = 1; // Start the timer, TMR3 count up<br />
//Input Capture Config====================================================<br />
IC2CONbits.ICM = 3; //Detect rising <br />
_IC2IF = 0; //Clear interrupt flag<br />
_IC2IE = 0; //Disable interrupt<br />
//Start Auto baud detection===============================================<br />
unsigned int i=0;<br />
cli(); //Disable Global Interrupt<br />
while(!_IC2IF); //1st rising edge detected<br />
TMR3 = 0; //Clear TMR3 to start count up<br />
_IC2IF = 0; //Clear interrupt flag<br />
while(!_IC2IF); //2nd rising edge detected<br />
_IC2IF = 0; //Clear interrupt flag<br />
while(!_IC2IF); //3rd rising edge detected<br />
_IC2IF = 0; //Clear interrupt flag<br />
while(!_IC2IF); //4th rising edge detected<br />
_IC2IF = 0; //Clear interrupt flag<br />
while(!_IC2IF); //5th rising edge detected<br />
_IC2IF = 0; //Clear interrupt flag<br />
T3CONbits.TON = 0; //Stop the timer<br />
sti(); //Enable Global Interrupt<br />
//Compute value for BRG register==========================================<br />
unsigned int time;<br />
time = ((TMR3+0x40)>>7)-1; //+0x40 for rounding<br />
//========================================================================<br />
return time;<br />
}<br />
*For 30MIP, tested speeds of transmission include 9600bps, 19200bps, 28800bps, 38400bps and 57600bps.<br />
====open()====<br />
*The following structures and variables are used as circular buffers for transmit and receive.<br />
struct UART_Rx{<br />
unsigned char wr;<br />
unsigned char rd;<br />
};<br />
struct UART_Tx{<br />
unsigned char wr; <br />
unsigned char rd;<br />
unsigned char tx_complete_flag;<br />
};<br />
struct UART_Rx uart_rx;<br />
struct UART_Tx uart_tx;<br />
unsigned char uart_rx_buf[MAX_UART_RX_BUF];<br />
unsigned char uart_tx_buf[MAX_UART_TX_BUF];<br />
<br />
char uart_open()<br />
{<br />
uart_rx.wr = 0;<br />
uart_rx.rd = 0;<br />
uart_tx.wr = 0;<br />
uart_tx.rd = 0;<br />
uart_tx.tx_complete_flag = 1;<br />
uart2_init();<br />
return 0;<br />
}<br />
<br />
void uart2_init(void){<br />
unsigned int u2brg = 97; <br />
#if(AUTO_BAUD_DECT>0)<br />
u2brg = uart2_autobaud();<br />
#endif<br />
U2BRG = u2brg; <br />
//=================================================================<br />
// Disable U2ART<br />
U2MODEbits.UARTEN = 0; //Disable U2ART module<br />
//=================================================================<br />
// Configure Interrupt Priority<br />
_U2RXIF = 0; //Clear Rx interrupt flags<br />
_U2TXIF = 0; //Clear Tx interrupt flags<br />
_U2RXIE = 1; //Receive interrupt: 0 disable, 1 enable <br />
_U2TXIE = 1; //Transmit interrupt: 0 disable, 1 enable<br />
//=================================================================<br />
// Configure Mode<br />
// +--Default: 8N1, no loopback, no wake in sleep mode, continue in idle mode<br />
// +--Diable autobaud detect<br />
// +--Enable U2ART module<br />
U2MODEbits.ABAUD = 0; //Disable Autobaud detect from U2RX <br />
U2MODEbits.UARTEN = 1; //U2ART enable<br />
//=================================================================<br />
// Configure Status<br />
// +--Default: TxInt when a char is transmitted, no break char<br />
// +--Default: RxInt when a char is received, no address detect, clear overflow<br />
// +--Enable Transmit<br />
U2STAbits.UTXEN = 1; //Tx enable<br />
}<br />
<br />
====write()====<br />
*This function writes a series of bytes to the circular buffer and start transmission.<br />
int uart_write(unsigned char *buf, int count)<br />
{<br />
//If transimt has not completed, return busy<br />
if(uart_tx.tx_complete_flag == 0){<br />
return -1; <br />
}<br />
else{<br />
uart_tx.tx_complete_flag = 0;<br />
}<br />
int next_data_pos;<br />
int byte = 0;<br />
for (; byte<count; byte++) {<br />
next_data_pos = pre_wr_cir254buf( (unsigned char)uart_tx.wr, <br />
(unsigned char)uart_tx.rd, <br />
MAX_UART_TX_BUF); <br />
if (next_data_pos!=255) {<br />
//Valid data is available<br />
uart_tx_buf[uart_tx.wr] = (unsigned char) buf[byte]; //copy the char to tx_buf<br />
uart_tx.wr = next_data_pos; //increment the ptr<br />
} else break;<br />
}<br />
//Raise Interrupt flag to initiate transmission<br />
_U2TXIF = 1; //Start interrupt<br />
return byte; <br />
}<br />
*The interrupt routine reads from the circular buffer and send the data. The uart is opened such that the module will generate an TX Interrupt when it a byte is sent.<br />
void _ISR _U2TXInterrupt(void){<br />
DISI_PROTECT(_U2TXIF = 0); //Clear Interrupt Flag<br />
unsigned char next_data_pos;<br />
next_data_pos = pre_rd_cir254buf( (unsigned char)uart_tx.wr,<br />
(unsigned char)uart_tx.rd, <br />
MAX_UART_TX_BUF);<br />
if (next_data_pos!= 255) {<br />
//Valid Data is available to transmit<br />
U2TXREG = (uart_tx_buf[(unsigned char)uart_tx.rd] & 0xFF); //send next byte...<br />
uart_tx.rd = (unsigned char) next_data_pos; //update rd pointer<br />
} else {<br />
//Transimission has completed<br />
uart_tx.tx_complete_flag = 1; // change to empty of tx<br />
}<br />
}<br />
<br />
====read()====<br />
*The interrupt routine writes to the circular buffer when space is available.<br />
void _ISR _U2RXInterrupt(void){<br />
unsigned char next_data_pos;<br />
if ( U2STAbits.URXDA ){<br />
next_data_pos = pre_wr_cir254buf( uart_rx.wr, uart_rx.rd, MAX_UART_RX_BUF);<br />
if (next_data_pos!=255) {<br />
//If buffer is not full<br />
uart_rx_buf[uart_rx.wr] = (unsigned char) U2RXREG; //Read the data from buffer<br />
uart_rx.wr = next_data_pos;<br />
} <br />
else{<br />
//When buffer is full, still remove data from register, butthe incoming data is lost<br />
next_data_pos = (unsigned char) U2RXREG; //Read the data from buffer<br />
} <br />
}<br />
DISI_PROTECT(_U2RXIF = 0); //Clear the flag<br />
}<br />
*This function reads one byte from the circular buffer.<br />
int uart_read(unsigned char *buf)<br />
{<br />
int next_data_pos;<br />
next_data_pos = pre_rd_cir254buf( uart_rx.wr, uart_rx.rd, MAX_UART_RX_BUF);<br />
//Copy 1 byte when data is available<br />
if (next_data_pos!=255) <br />
{<br />
*buf = uart_rx_buf[uart_rx.rd]; //copy the stored data to buf<br />
uart_rx.rd = next_data_pos; //update the ptr<br />
return 1;<br />
}<br />
//No data can be copied<br />
else<br />
{<br />
return 0;<br />
} <br />
}<br />
<br />
===I<sup>2</sup>C===<br />
<br />
----<br />
*Two lines are devoted for the serial communication. SCL for clock, SDA for data.<br />
*Standard communication speed includes<br />
#Standard speed mode: 100kHz<br />
#Fast speed mode: 400kHz<br />
#High speed mode: 3.4MHz<br />
*dsPIC30f5011 supports standard and fast speed modes. The maximum speed attainable is 1MHz.<br />
*Pull-up resistors are required for both SCL and SDA. Minimum pull-up resistance is given by:<br />
Pull-up resistor (min) = (V<sub>dd</sub>-0.4)/0.003 ...... [See section 21.8 in Family reference manual]<br />
*2.2Kohm is typical for standard speed mode.<br />
*After initiating a start/stop/restart bit, add a small delay (e.g. no operation) before polling the corresponding control bit (hardware controlled).<br />
*After sending a byte and receiving an acknowledgement from the slave device, ensure to change to idle state.<br />
<br />
====open()====<br />
*The following structure is used to record whether special bits are needed to be sent.<br />
typedef union{<br />
unsigned char val;<br />
struct{<br />
unsigned START:1; //start<br />
unsigned RESTART:1; //restart<br />
unsigned STOP:1; //stop<br />
unsigned NACK:1; //not acknowledgment<br />
unsigned :1;<br />
unsigned :1;<br />
unsigned :1;<br />
unsigned :1; <br />
}bits;<br />
} I2C_STATUS;<br />
static I2C_STATUS i2c_status; <br />
<br />
*Initializing I<sup>2</sup>C with default speed I2C_BRG without interrupts.<br />
void i2c_open(void)<br />
{<br />
//Open i2c if not already opened<br />
if(I2CCONbits.I2CEN == 0)<br />
{<br />
_SI2CIF = 0; //Clear Slave interrupt<br />
_MI2CIF = 0; //Clear Master interrupt<br />
_SI2CIE = 0; //Disable Slave interrupt<br />
_MI2CIE = 0; //Disable Master interrupt<br />
I2CBRG = I2C_BRG;<br />
I2CCONbits.I2CEN = 1; //Enable I2C module <br />
i2cIdle(); //I2C bus at idle state, awaiting transimission<br />
i2c_status.val = 0; //clear status flags<br />
}<br />
}<br />
<br />
====ioctl()====<br />
*Use this function before read/write to append special bits before or after the data byte.<br />
char i2c_ioctl(unsigned char request, unsigned char* argp)<br />
{<br />
switch(request){<br />
case I2C_SET_STATUS:<br />
i2c_status.val = *argp;<br />
break;<br />
default:<br />
return -1; //request code not recognised <br />
}<br />
return 0;<br />
}<br />
<br />
====write()====<br />
*This function sends an 8-bit data using the I2C protocol.<br />
Mst/Slv _______ M ____M___ S M ________ <br />
SDA (Data) |S| data |A|S|<br />
|T| |C|T|<br />
|A|XXXXXXXX|K|P|<br />
*Use ioctl() to select whether a start/restart/stop bit is required.<br />
*If slave does not respond after ACK_TIMEOUT, the transmission is considered unsucessful.<br />
int i2c_write(unsigned char *buf)<br />
{<br />
unsigned int count = 0;<br />
if(i2c_status.bits.START)<br />
{<br />
I2CCONbits.SEN = 1; <br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.SEN); //Wait till Start sequence is completed<br />
}<br />
else if(i2c_status.bits.RESTART)<br />
{<br />
I2CCONbits.RSEN = 1; <br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.RSEN); //Wait till Start sequence is completed<br />
}<br />
I2CTRN = *buf; //Transmit register<br />
while(I2CSTATbits.TBF); //Wait for transmit buffer to empty<br />
while(I2CSTATbits.ACKSTAT){<br />
if(++count > ACK_TIMEOUT){<br />
//Slave did not acknowledge, byte did not transmit sucessfully, <br />
//send stop bit to reset i2c<br />
I2CCONbits.PEN = 1;<br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.PEN); //Wait till stop sequence is completed<br />
i2cIdle();<br />
return 0;<br />
}<br />
}<br />
i2cIdle();<br />
if(i2c_status.bits.STOP)<br />
{<br />
I2CCONbits.PEN = 1;<br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.PEN); //Wait till stop sequence is completed<br />
i2cIdle();<br />
}<br />
i2c_status.val = 0; //Clear status<br />
return 1;<br />
}<br />
<br />
====read()====<br />
*This function reads 1 byte from slave using the I2C protocol.<br />
Mst/Slv ____ ___S____ M M _____ <br />
SDA (Data) | data |A|S|<br />
| |C|T|<br />
|XXXXXXXX|K|P|<br />
*Use ioctl() to select whether an ACK/NACK and/or STOP bit is needed to be sent.<br />
int i2c_read(unsigned char *buf)<br />
{<br />
I2CCONbits.RCEN = 1; //Enable Receive<br />
while(I2CCONbits.RCEN);<br />
I2CSTATbits.I2COV = 0; //Clear receive overflow<br />
*buf = (unsigned char) I2CRCV; //Access the receive buffer<br />
I2CCONbits.ACKDT = (i2c_status.bits.NACK)? 1 : 0;<br />
I2CCONbits.ACKEN = 1; //Send Acknowledgement/Not Acknowledgement<br />
i2cIdle(); //I2C bus at idle state, awaiting transimission<br />
if(i2c_status.bits.STOP)<br />
{<br />
I2CCONbits.PEN = 1;<br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.PEN); //Wait till stop sequence is completed<br />
i2cIdle();<br />
}<br />
i2c_status.val = 0; //Clear status<br />
return 1;<br />
}<br />
<br />
====Example====<br />
Mst/Slv _______ M ___M___ M S ____M___ S M ___M___ M S ___S____ M ___S____ M M _____ <br />
SDA (Data) |S| | |A| |A|R| | |A| |A| |N|S|<br />
|T|address|W|C|channelA|C|E|address|R|C| Data H |C| Data L |A|T|<br />
|A|1001111|0|K|00010010|K|S|1001111|1|K|10101010|K|10XXXXXX|K|P|<br />
<br />
/*<br />
* Send start bit, slave address (Write Mode)<br />
*/ <br />
status = I2C_START;<br />
i2c_ioctl(I2C_SET_STATUS, &status);<br />
data = (unsigned char) I2C_SLAVE_ADDR;<br />
i2c_write(&data);<br />
/*<br />
* Send control byte: Channel select<br />
*/<br />
data = (unsigned char) ctrl_byte;<br />
i2c_write(&data);<br />
/*<br />
* Send restart bit, slave address (Read Mode)<br />
*/<br />
status = I2C_RESTART;<br />
i2c_ioctl(I2C_SET_STATUS, &status);<br />
data = (unsigned char) (I2C_SLAVE_ADDR|0x01);<br />
i2c_write(&data);<br />
/*<br />
* Receive High Byte with Acknowledgment<br />
*/<br />
i2c_read(&data);<br />
usr_data.high = (unsigned char) data;<br />
/*<br />
* Receive Low Byte with Not Acknowledgment and stop bit<br />
*/ <br />
status = I2C_NACK | I2C_STOP;<br />
i2c_ioctl(I2C_SET_STATUS, &status);<br />
i2c_read(&data);<br />
usr_data.low = (unsigned char) data;<br />
<br />
===ADC===<br />
<br />
----<br />
*12-bit ADC: (Max 16 Channels)<br />
*Allow a maximum of 2 sets of analog input multiplexer configurations, MUX A and MUX B (Normally use one only).<br />
*A maximum of 200kps of sampling rate when using auto sampling mode.<br />
====open()====<br />
*The following variables are required.<br />
unsigned int adc_buf[ADC_MAX_CH]; //Store most updated data<br />
volatile unsigned int* ADC16Ptr = &ADCBUF0; //Pointer to ADC register buffer, <br />
unsigned char adc_ch_select = 0; //Pointer to channel to be read from<br />
unsigned char adc_data_ready = 0; //Indicate if RAM data is ready for output<br />
*Configuration is highlighted below.<br />
**Interrupt: The ADC module will be set to interrupt when the specified channels are updated.<br />
**I/O: Set the corresponding TRISBX bits (digit i/o config) to input (i.e. = 1), and set corresponding bits in ADPCFG (analog config) to zero.<br />
**Scanning Mode: Scan mode is used. In this mode, the Sample and Hold (S/H) is switched between the channels specified by ADCSSL (Scan select register).<br />
**Reference Voltage for S/H: Only MUX A is used. By default, the negative reference voltage of the S/H is connected to V<sub>REF-</sub>.<br />
**Settings for ADC Operation: For 200kbps operation, the voltage references for the ADC voltage are connected to V<sub>REF+</sub> and V<sub>REF-</sub>. Scan input is enabled, and the module will generate an interrupt when all selected channels have been scanned.<br />
**Sampling Rate: T<sub>AD</sub> refers to the time unit for the ADC clock. To configure the ADC module at 200kbps, the minimum sampling time of 1T<sub>AD</sub> = 334ns is required. ADCS<5:0> in ADCON3 register is used to set the time, which is given by:<br />
ADCS<5:0> = 2(T<sub>AD</sub>/T<sub>CY</sub>)-1 <br />
= 2(334e-9/33.34e-9)-1 <br />
= 19<br />
<br />
char adc_open(int flags)<br />
{<br />
// Configure interrupt<br />
_ADIF = 0; //clear ADC interrupt flag<br />
_ADIE = 1; //enable adc interrupt<br />
// Configure analog i/o <br />
_TRISB0 = 1;<br />
_TRISB1 = 1; <br />
ADPCFG = 0xFFFC; //Enable AN0 (Vref+) and AN1 (Vref-)<br />
// Configure scan input channels <br />
ADCSSL = 0x0003; //0 => Skip, 1 => Scan<br />
// Configure CH0 Sample and Hold for 200kbps<br />
// +-- Use MUX A only<br />
// +-- Set CH0 S/H -ve to VRef-<br />
ADCHSbits.CH0NA = 0;<br />
// ADCCON3:<br />
// +--Auto Sample Time = 1TAD<br />
// +--A/D Conversion Clock Source = system clock<br />
// +--A/D Conversion Clock Select ADCS<5:0>= 2(TAD/TCY)-1<br />
// 200kbps(Sampling frequency)<br />
ADCON3bits.SAMC = ADC_ACQ_TIME; //1TAD for sampling time<br />
ADCON3bits.ADRC = 0; //Use system clock<br />
ADCON3bits.ADCS = ADC_ADCS; //each conversion requires 14TAD<br />
// ADCCON2:<br />
// +--Default: Use MUX A, No splitting of Buffer<br />
// +--Voltage Reference Configuration Vref+ and Vref-<br />
// +--Scan Input Selections<br />
// +--5 samples between interrupt<br />
ADCON2bits.VCFG = 3; //External Vref+, Vref-<br />
ADCON2bits.CSCNA = 1; //Scan input<br />
ADCON2bits.SMPI = 1; //take 2 samples (one sample per channel) per interrupt<br />
// ADCCON1:<br />
// +--Default: continue in idle mode, integer format<br />
// +--Enable ADC, Conversion Trigger Source Auto, Auto sampling on<br />
ADCON1bits.FORM = 0; //[0:integer]; [2 fractional]; [3 siged fractional]<br />
ADCON1bits.SSRC = 7; //auto covert, using internal clock source<br />
ADCON1bits.ASAM = 1; //auto setting of SAMP bit<br />
ADCON1bits.ADON = 1; //Turn on module<br />
return 0;<br />
}<br />
<br />
====read()====<br />
*16 registers (ADCBUF0 -ADCBUF15) are dedicated to store the ADC data between interrupts. However, the data in ADCBUFx does not necessarily correspond to the data taken for channel x. Since the lowest register will always be filled first, when some of the channels are not scanned (i.e. skipped), care must be taken. The following code checks the ADCSSL register for the current scanning channels and moves the data to the corresponding position in *adc_buf.<br />
void _ISR _ADCInterrupt(void){<br />
unsigned int channel = 0;<br />
unsigned int buffer = 0;<br />
for (; channel<ADC_MAX_CH; channel++)<br />
{<br />
if(select(channel)) //Check if channel has been selected<br />
{<br />
adc_buf[channel] = ADC16Ptr[buffer]; //Copy data to adc_buf<br />
buffer++;<br />
}<br />
}<br />
adc_data_ready = 1;<br />
DISI_PROTECT(_ADIF = 0); //Clear adc interrupt<br />
}<br />
<br />
static unsigned char select(unsigned char ch)<br />
{<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
if(ADCSSL & mask)<br />
return 1;<br />
return 0;<br />
}<br />
*User can read from the buffer at anytime to get the most updated analog values.<br />
int adc_read(unsigned int* buf, int count)<br />
{<br />
if(adc_data_ready == 1)<br />
{<br />
int num_channel = count/2; //number of channels to read<br />
unsigned char channel = adc_ch_select; //index for adc_buf<br />
int i = 0; //index for buf<br />
while(i<num_channel && channel<ADC_MAX_CH)<br />
{ <br />
//Loop only for specified number of channel or all channels <br />
buf[i++] = adc_buf[channel++]; //use data in local buffer<br />
while(select(channel)==0)<br />
{ //increment to next valid channel<br />
channel++; <br />
if(channel >= ADC_MAX_CH) break;<br />
}<br />
}<br />
return 2*i;<br />
}<br />
return -1;<br />
}<br />
<br />
====ioctl()====<br />
*This function is used to add or remove channels from the ADC scanning process.<br />
char adc_ioctl(unsigned char request, unsigned char* argp)<br />
{<br />
switch(request)<br />
{<br />
case ADC_ADD_CH:<br />
//ADD channels to current set==========================<br />
cli(); //Disable global interrupt<br />
if(select(argp[0]) == 0){ //If channel not in scan list<br />
adcAdd(argp[0]); //Add individual channel to scan list<br />
adc_data_ready = 0; //First data not ready yet, until interrupt occurs<br />
}<br />
adc_ch_select = argp[0]; //Select current channel for reading<br />
sti(); //Enable global interrupt<br />
break;<br />
case ADC_RM_CH:<br />
//REMOVE channels from current set==========================<br />
cli(); //Disable global interrupt<br />
if(select(argp[0])){ //If channel in scan list <br />
adcRm(argp[0]); //Remove individual channel<br />
adc_ch_select = 0; //Reset to AN0<br />
}<br />
sti(); //Enable global interrupt<br />
break;<br />
default:<br />
return -1; //request code not recognised <br />
}<br />
return 0;<br />
}<br />
*Channels may be added or removed by changing _TRISBX, ADPCFG, ADCSSL and ADCON2bits.SMPI.<br />
void adc_add_ch(unsigned char ch){<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
TRISB = TRISB | mask;<br />
ADCSSL = ADCSSL | mask; <br />
ADPCFG = ~ADCSSL;<br />
ADCON2bits.SMPI++; //take one more sample per interrupt<br />
}<br />
<br />
void adc_rm_ch(unsigned char ch){<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
ADPCFG = ADPCFG | mask;<br />
ADCSSL = ~ADPCFG;<br />
ADCON2bits.SMPI--; //take one less sample per interrupt<br />
}<br />
<br />
===EEPROM===<br />
<br />
----<br />
*5011 has 1024 bytes of EEPROM, readable and writable under normal voltage (5V).<br />
*To use, declare:<br />
unsigned char _EEDATA(2) eeData[1024]={ 0x00, 0x00, 0x00, 0x00, .... }<br />
unsigned int byte_pointer = 0;<br />
====lseek()====<br />
*This function moves the pointer to the desired position before a reading/writing operation is performed.<br />
int eeprom_lseek(int offset, unsigned char whence){<br />
byte_pointer = offset;<br />
return byte_pointer;<br />
}<br />
====read()====<br />
*This function read ''count'' bytes from the eeprom.<br />
int eeprom_read(unsigned char* buf, int count){<br />
int i=0;<br />
for(; i<count && byte_pointer < 1024; i++){<br />
readEEByte( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + byte_pointer, <br />
&buf[i]);<br />
byte_pointer++; //Update global pointer<br />
}<br />
return i; //read i bytes successful <br />
}<br />
*readEEByte() is implemented in assembly code as follows:<br />
.global _readEEByte<br />
_readEEByte:<br />
push TBLPAG ;w0 = base of eeData<br />
mov w0, TBLPAG ;w1 = offset for eeData in byte<br />
tblrdl.b [w1], [w2] ;w2 = pointer to user buffer<br />
pop TBLPAG<br />
return<br />
<br />
====write()====<br />
*This function write ''count'' bytes to eeprom.<br />
int eeprom_write(unsigned char* buf, int count){<br />
char isOddAddr = byte_pointer%2; //current address is odd<br />
char isOddByte = count%2; //number of bytes to write is odd<br />
//=================================================================<br />
unsigned int word_offset = byte_pointer>>1; //div by 2 and round down<br />
int max_write;<br />
max_write = (isOddAddr == 0 && isOddByte == 0) ? (count>>1) : (count>>1)+1;<br />
//=================================================================<br />
unsigned int word_data; //Store word to be written<br />
int byte_wr = 0; //number of bytes written, i.e buffer pointer<br />
int i = 0;<br />
//=================================================================<br />
for(; i<max_write && word_offset<512; i++, word_offset++){<br />
if(i==0 && isOddAddr){<br />
//First byte not used<br />
//============================================save first byte<br />
readEEByte( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + byte_pointer - 1,<br />
&word_data);<br />
//===========================================================<br />
word_data = ((unsigned int)buf[0] << 8) + (0xFF & word_data);<br />
byte_wr++; //Update buffer pointer<br />
byte_pointer++; //Update global pointer<br />
} else if(i==max_write-1 && ((isOddAddr && sOddByte==0)||(isOddAddr==0 && isOddByte))){<br />
//Last byte not used<br />
//=============================================save last byte<br />
readEEByte( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + byte_pointer + 1,<br />
&word_data);<br />
//============================================================<br />
word_data = (word_data << 8) + buf[byte_wr];<br />
byte_wr++; //Update buffer pointer<br />
byte_pointer++; //Update global pointer<br />
} else{<br />
//Both bytes valid<br />
word_data = ((unsigned int)buf[byte_wr+1] << 8) + buf[byte_wr];<br />
byte_wr+=2; //Update buffer pointer<br />
byte_pointer+=2; //Update global pointer<br />
}<br />
//==================================================================<br />
eraseEEWord( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + 2*word_offset);<br />
writeEEWord( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + 2*word_offset,<br />
&word_data);<br />
//==================================================================<br />
}<br />
return byte_wr; //No. of byte written<br />
}<br />
*eraseEEWord and writeEEWord are implemented in assembly.<br />
.global _eraseEEWord<br />
_eraseEEWord:<br />
push TBLPAG <br />
mov w0, NVMADRU ;w0 = base of eeData<br />
mov w1, NVMADR ;w1 = offset for eeData in word<br />
mov #0x4044, w0 <br />
mov w0, NVMCON ;Set to erase operation<br />
push SR ;Disable global interrupts<br />
mov #0x00E0, w0<br />
ior SR<br />
mov #0x55, w0 ;Write the KEY sequence<br />
mov w0, NVMKEY<br />
mov #0xAA, w0 <br />
mov w0, NVMKEY<br />
bset NVMCON, #15 ;Start the erase cycle, bit 15 = WR<br />
nop<br />
nop<br />
L1: btsc NVMCON, #15 ;while(NVMCONbits.WR)<br />
bra L1<br />
clr w0<br />
pop SR ;Enable global interrupts<br />
pop TBLPAG<br />
return<br />
<br />
.global _writeEEWord<br />
_writeEEWord:<br />
push TBLPAG ;w0 = base of eeData<br />
mov w0, TBLPAG ;w1 = offset for eeData in byte<br />
tblwtl [w2], [w1] ;w2 = pointer to user buffer<br />
mov #0x4004, w0 ;Set to write operation<br />
MOV w0, NVMCON<br />
push SR ;Disable global interrupts<br />
mov #0x00E0, w0<br />
ior SR<br />
mov #0x55, w0 ;Write the KEY sequence<br />
mov w0, NVMKEY<br />
mov #0xAA, w0 <br />
mov w0, NVMKEY<br />
bset NVMCON, #15 ;Start the erase cycle, bit 15 = WR<br />
nop<br />
nop<br />
L2: btsc NVMCON, #15 ;while(NVMCONbits.WR)<br />
bra L2<br />
clr w0<br />
pop SR ;Enable global interrupts<br />
pop TBLPAG<br />
return<br />
<br />
===Simple PWM (Output Compare Module)===<br />
<br />
----<br />
<br />
*The PWM module consists of 8 channels using the output compare module of dsPic.<br />
*These channels are locate at pin 46 (OC1), 49 (OC2), 50 (OC3), 51 (OC4), 52 (OC5), 53 (OC6), 54 (OC7), 55 (OC8). These pins are shared with port D.<br />
*The range of PWM freqeuencies obtainable is 2Hz to 15MHz (See Figure 6.3). Suggested range of operation is 2Hz to 120kHz. The relationship between resolution ''r'' and PWM frequency ''f''<sub>PWM</sub> is given by:<br />
f<sub>PWM</sub> = f<sub>CY</sub>/(Prescale*10<sup>rlog(2)</sup>)<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 6.3 Relationship of Resolution and PWM Frequency<br />
! Resolution (bit) !! Prescale=1 !! Prescale=8 !! Prescale=64 !! Prescale=256<br />
|- <br />
|1||15,000,000 ||1,875,000 ||234,375||58,594 <br />
|- <br />
|2||7,500,000 ||937,500 ||117,188 ||29,297 <br />
|- <br />
|3||3,750,000 ||468,750 ||58,594 ||14,648 <br />
|- <br />
|4||1,875,000 ||234,375 ||29,297 ||7,324 <br />
|- <br />
|5||937,500 ||117,188 ||14,648 ||3,662 <br />
|- <br />
|6||468,750 ||58,594 ||7,324 ||1,831 <br />
|- <br />
|7||234,375 ||29,297 ||3,662 ||916 <br />
|- <br />
|8||117,188 ||14,648 ||1,831||458 <br />
|- <br />
|9||58,594 ||7,324 ||916 ||229 <br />
|- <br />
|10||29,297 ||3,662 ||458 ||114 <br />
|- <br />
|11||14,648 ||1,831 ||229||57 <br />
|- <br />
|12||7,324 ||916 ||114 ||29 <br />
|- <br />
|13||3,662 ||458 ||57 ||14 <br />
|- <br />
|14||1,831 ||229 ||29 ||7 <br />
|- <br />
|15||916 ||114 ||14 ||4 <br />
|- <br />
|16||458 ||57 ||7 ||2 <br />
|-<br />
|}<br />
<br />
====open()====<br />
*A timer (either Timer 2 or 3) is needed to determine the pwm period. The following code uses timer 2 for all 8 channels.<br />
void pwm_open(void){<br />
OC1CON = 0; OC2CON = 0; //Disable all output compare modules<br />
OC3CON = 0; OC4CON = 0;<br />
OC5CON = 0; OC6CON = 0;<br />
OC7CON = 0; OC8CON = 0;<br />
//============================================================<br />
TMR2 = 0; // Clear register<br />
PR2 = 0xFFFF; // Set to Maximum<br />
//============================================================<br />
_T2IF = 0; // Clear interrupt flag<br />
_T2IE = 0 // Enable interrupts<br />
//============================================================<br />
T2CONbits.TCS = 0; // Use internal clock source<br />
T2CONbits.TCKPS = 0; // Prescale Select 1:1<br />
//============================================================<br />
T2CONbits.TON = 1; // Start the timer <br />
}<br />
<br />
====ioctl()====<br />
*User should select the channel and set the pwm period using the functions below before issuing the duty cycle:<br />
char pwm_ioctl(unsigned char request, unsigned long* argp){<br />
unsigned int value;<br />
unsigned char mask;<br />
switch(request){<br />
case PWM_SET_PERIOD:<br />
return setPeriodNPrescale(argp[0]);<br />
case PWM_SELECT_CH:<br />
pwm_channel = argp[0];<br />
mask = 0x01 << pwm_channel;<br />
pwm_status = pwm_status | mask;<br />
return 0;<br />
default:<br />
return -1;<br />
}<br />
}<br />
char setPeriodNPrescale(unsigned long value_ns){<br />
unsigned long ans;<br />
unsigned long long numerator = (unsigned long long)value_ns*SYSTEM_FREQ_MHZ;<br />
int index= -1;<br />
unsigned long denominator;<br />
//-------------------------------------------------<br />
do{<br />
denominator = (unsigned long)1000*pwm_prescale[++index];<br />
ans = (unsigned long)(((long double)numerator/denominator) + 0.5) - 1; //round to nearest int<br />
} while(ans > 0x0000FFFF && index < 3);<br />
//-------------------------------------------------<br />
if(ans > 0x0000FFFF)<br />
return -1;<br />
//-------------------------------------------------<br />
T2CONbits.TON = 0; // Turn off the timer<br />
T2CONbits.TCKPS = index; // Change prescale factor<br />
PR2 = (unsigned int) ans; // Set to Maximum<br />
T2CONbits.TON = 1; // Turn on the timer <br />
//-------------------------------------------------<br />
return 0;<br />
}<br />
<br />
====write()====<br />
*User can change the duty cycle using the following functions<br />
int pwm_write(unsigned long* buf){<br />
if((pwm_status & (0x01 << pwm_channel)) == 0){<br />
return -1; //Channel has not been enabled<br />
}<br />
switch(pwm_channel){<br />
case 0:<br />
OC1RS = calcDCycle(buf[0]); OC1R = OC1RS; <br />
OC1CONbits.OCM = 6; //Simple PWM, Fault pin disabled<br />
break;<br />
case 1:<br />
OC2RS = calcDCycle(buf[0]); OC2R = OC2RS; <br />
OC2CONbits.OCM = 6; //Simple PWM, Fault pin disabled<br />
break;<br />
...<br />
case 7:<br />
OC8RS = calcDCycle(buf[0]); OC8R = OC8RS; <br />
OC8CONbits.OCM = 6; //Simple PWM, Fault pin disabled<br />
break; <br />
default:<br />
return -1;<br />
}<br />
return 4;<br />
}<br />
unsigned int calcDCycle(unsigned long value_ns){<br />
unsigned long long numerator = (unsigned long long)value_ns*SYSTEM_FREQ_MHZ;<br />
unsigned int index = T2CONbits.TCKPS;<br />
unsigned long denominator = (unsigned long)1000*pwm_prescale[index];<br />
return (unsigned int)(((long double)numerator/denominator) + 0.5) - 1; //round to nearest int<br />
}<br />
<br />
====Propagration Delay====<br />
*PWM channels sharing the same timer will have their PWM signals synchronised (i.e. the HIGH state of the duty cycle are all triggered together).<br />
*To introduced delay to the PWM signals, the signal from selected channels may be made to pass through a series of inverters (e.g. 74HC14D). This adds propagation delay to the signal.<br />
*However, as propagration delay of logic gates depends on applied voltage, temperature and load capacitance, the accuracy is low and performance is poor. For accurate delay, delay lines may be used, but they are expensive.<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 6.4 Propagation Delay of [http://www.nxp.com/acrobat_download/datasheets/74HC_HCT14_3.pdf Philips 74HC14D]<sup>[1], [2]</sup><br />
! !! 3.3V !! !! !! 5.0V !! !!<br />
|- <br />
! Number of Gates !! A !! B !! C !! A !! B !! C<br />
|- <br />
| 2 <br />
| 21ns (10.5)|| 23ns (11.5)|| 22ns (11.0)<br />
| 15ns (7.5)|| 14ns (7.0)|| 14ns (7.0)<br />
|-<br />
| 4 <br />
| 45ns (11.3)|| 46ns (11.5)|| 46ns (11.5) <br />
| 30ns (7.5)|| 30ns (7.5)|| 30ns (7.5)<br />
|-<br />
| 6 <br />
| 69ns (11.5)|| 70ns (11.7)|| 72ns (12.0) <br />
| 45ns (7.5)|| 46ns (7.7)|| 47ns (7.8)<br />
|- <br />
|}<br />
[1] Data in specification for 4.5V: Typical 15ns, Maximum 25ns<br><br />
[2] Data in specification for 6.0V: Typical 12ns, Maximum 21ns<br />
<br />
===DSP Library===<br />
<br />
----<br />
*Library functions in <dsp.h> include the following categories: <br />
#Vector<br />
#Window<br />
#Matrix<br />
#Filtering<br />
#Transform<br />
#Control<br />
<br />
====Data Types====<br />
*Signed Fractional Value (1.15 data format)<br />
**Inputs and outputs of the dsp functions adopt 1.15 data format, which consumes 16 bits to represent values between -1 to 1-2<sup>-15</sup> inclusive.<br />
**Bit<15> is a signed bit, positive = 0, negative = 1.<br />
**Bit<14:0> are the exponent bits ''e''.<br />
**Positive value = 1 - 2<sup>-15</sup>*(32768 - ''e'')<br />
**Negative value = 0 - 2<sup>-15</sup>*(32768 - ''e'')<br />
*40-bit Accumulator operations (9.31 data format)<br />
**The dsp functions use the 40 bits accumalators during arithmatic calculations.<br />
**Bit<39:31> are signed bits, positive = 0x000, negative = 0x1FF.<br />
**Bit<30:0> are exponent bits.<br />
*IEEE Floating Point Values<br />
**Fractional values can be converted to Floating point values using: '''fo = Fract2Float(fr);''' for fr = [-1, 1-2<sup>-15</sup>]<br />
**Floating point values can be converted to Fractional values using: '''fr = Float2Fract(fo);''' or '''fr = Q15(fo);''' for fo = [-1, 1-2<sup>-15</sup>]<br />
**Float2Fract() is same as Q15(), except having saturation control. When +ve >= 1, answer = 2<sup>15</sup>-1 = 32767 (0x7FFF). When -ve < -1, answer = -2<sup>15</sup> = -32767 (0x8000)<br />
<br />
===Build-in Library===<br />
<br />
----<br />
*Some assembler operators can only be accessed by inline assembly code, for example, <br />
#Manuipulation of accumulators A and B (add, sub, mul, divide, shift, clear, square)<br />
#Bit toggling<br />
#Access to psv (program space visiblity) page and offset<br />
#Access to table instruction page and offset<br />
*Built-in functions are written as C-like function calls to utilize these assembler operators.<br />
<br />
<br />
==Bootloader Development==<br />
<br />
===Concepts===<br />
*Programming with ICSP is useful when the target board is produced in batch. The producer can download a program even when the chip is on the target board.<br />
*However, ICSP requires an external programmer.<br />
*To allow the user to change the program after production but without the need of an external programmer, bootloader becomes useful.<br />
*Bootloader is a small program installed via ICSP. Everytime the device is reset, the bootloader is run first. The bootloader first detects the default serial channel whether the user wishes to download a new program to the device. If so, the bootloader will pause there, and wait for the user to download the hex file from the PC. The hex file is written to the device via RTSP instructions in the bootloader. If a new download is not necessary, the bootloader redirects to the previously installed user's program.<br />
*The disadvantage of bootloaders is that they consume some of the memory of the device.<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 7.1 Free bootloaders for dsPIC<br />
! Developer<br />
! Source<br />
! Platform<br />
! User Guide<br />
! Remarks<br />
|- valign="top"<br />
| [http://www.ingenia-cat.com/index.php?lang=en ingenia]<br />
| [http://www.ingenia-cat.com/download/iBL.s Assembly]<br />
| [http://www.ingenia-cat.com/download/ingeniadsPICbootloader1.1.zip Windows]<br />
| [http://www.ingenia-cat.com/reference/pdf/iBL.UG.V1.2.pdf pdf]<br />
| <br />
*Works for all dsPIC supporting RTSP<br />
*Auto baudrate detection<br />
*Use about 1.15% of the flash memory space (0xAFFF-0xAE00)/(0xAFFF-0x0100)<br />
*Development of Linux platform is underway<br />
*Modification of code for dsPIC30F5011 is successful<br />
|-valign="top"<br />
| [http://www.etc.ugal.ro/cchiculita/software/picbootloader.htm Tiny]<br />
| [http://www.etc.ugal.ro/cchiculita/software/tinybld191.zip Assembly]<br />
| Windows<br />
| [http://www.etc.ugal.ro/cchiculita/software/tinybldusage.htm Web]<br />
| <br />
*By default, only supports 601X, 601X, 401X, 2010<br />
*Smaller code size than ingenia, but not as easy to modify<br />
|-valign="top"<br />
| [http://www.via.si/software/dsPIC_bootloader/ Elektronika]<br />
| [http://www.via.si/software/dsPIC_bootloader/data/ Hex]<br />
| Windows<br />
| [http://www.via.si/software/dsPIC_bootloader/data/README.txt txt]<br />
| <br />
*Only works for dsPIC30F6014 serial port UART2 at baudrate 57600<br />
|-<br />
|}<br />
<br />
===dsPicBootloader===<br />
<br />
*The bootloader developed by ingenia is open source and it has been modified (see below) to suit our development using dsPic30f5011.<br />
*The bootloader (hereafter called dsPicBootloader) employs the following settings:<br />
# Use U2ART channel<br />
# Use FRC, PLL16<br />
# For 5011, the bootloader is located between 0x00AE00 to 0x00AFFE (512bytes). Refer to C:\Program Files\Ingenia\ingeniadsPICbootloader\ibl_dspiclist.xml after installing the GUI interface.<br />
*Changes made to [http://www.ingenia-cat.com/download/iBL.s assembly code] includes:<br />
1. including p30f5011.gld and p30f5011.inc<br />
.include "p30f5011.inc"<br />
2. changing the config code of UART #0x8420 -> #0x8020<br />
; Uart init<br />
mov '''#0x8020''', W0 ; W0 = 0x8020 -> 1000 0000 0010 0000b<br />
mov W0, U2MODE ; Enable UART, AutoBaud and 8N1<br />
clr U2STA<br />
3. changing the start address 0xAE00 - 0x0100 = 0AD00<br />
.equ CRC, W4<br />
.equ ACK, 0x55<br />
.equ NACK, 0xFF<br />
.equ USER_ADDRESS, 0x0100<br />
.equ START_ADDRESS, '''0xAD00''' ; Relative to 0x0100<br />
4. using Internal FRC and PLL16<br />
config __FOSC, CSW_FSCM_OFF & '''FRC_PLL16''' ;Turn off clock switching and<br />
;fail-safe clock monitoring and<br />
;use the Internal Clock as the<br />
;system clock<br />
5. disabling MCLR (optional)<br />
config __FBORPOR, PBOR_ON & BORV_27 & PWRT_16 & '''MCLR_DIS'''<br />
;Set Brown-out Reset voltage and<br />
;and set Power-up Timer to 16msecs<br />
6. changing all the related registers of U1ART to U2ART, all U1XXX => U2XXX<br />
'''U2MODE, U2STA, U2BRG, U2RXREG, U2TXREG'''<br />
7. changing all the related registers of IC1 to IC2, all IC1XXX => IC2XXX<br />
'''IC2CON, #IC2IF, #IC2IE'''<br />
<br />
===dsPicProgrammer (Java-based Multi-Platformed)===<br />
*Ingenia developed a programmer (PC-side) that works only in Windows environment. The project for Linux environment is currently suspended.<br />
*A simple programmer (hereafter called dsPicProgrammer) written in Java based on the library developed by [http://www.rxtx.org/ RXTX] has been developed here. The programmer supports both Linux and Windows environments, and may be used as a substitution for the official programmer developed by ingenia.<br />
*The programmer has the following specification and limitations:<br />
#Can be used on both Linux and Windows platforms.<br />
#Adjustable baudrate (9600bps to 57600bps<sup>[1]</sup>).<br />
#Support programming of dsPIC30F5011 and dsPIC33FJ128GP306<sup>[2]</sup> devices (Developers may add your devices).<br />
#Protection against overwriting bootloader codes on devices.<br />
#Detection if application program does not have its reset() at user's code start address.<br />
#Reprogramming can be done without powering down the target board, provided the user's program is compliant to that stated below.<br />
#Target board will run the user's program after programming is done.<br />
#Can be used with USB-Serial Cables. Below is a list of tested cable:<br />
::[http://www.prolific.com.tw/eng/Products.asp?ID=59 Prolific PL-2303 USB to Serial Bridge Controller]: [http://www.prolific.com.tw/eng/downloads.asp?ID=31 Driver download]<br />
'''NOTE:'''<br><br />
[1] from version 1.5.2 onwards, the baudrate is increased to 115200bps.<br><br />
[2] only dsPIC30 devices are compatible with the ingenia's programmer. For dsPIC33 devices, the protocol has been modified due to the increased flash size, and the dsPIC33 bootloader can only work with dsPicProgrammer.<br />
<br />
===Special Consideration===<br />
*The bootloader assumes that the user program starts at address 0x100. This is usually the case, but there are always exceptions.<br />
*To ensure that the user program always starts at address 0x100, you can create a customized linker script and customized reset() function as follows:<br />
:*Copy and modify the file named "crt0.s" from the directory "C:\Program Files\Microchip\MPLAB C30\src\pic30" to the project directory and include it.<br />
.section .reset, code //previously .section .libc, code <br />
:*Copy and modify the linkerscript for the device (e.g. p30f5011.gld) to the project directory and include it.<br />
.text __CODE_BASE :<br />
{<br />
*(.reset); //<-insert this line here<br />
*(.handle);<br />
*(.libc) *(.libm) *(.libdsp); /* keep together in this order */<br />
*(.lib*);<br />
*(.text);<br />
} >program<br />
<br />
===Communication Protocol===<br />
<br />
+-------------------+ +-------------------+----------------+<br />
| dsPicProgrammer | | dsPicBootloader | User's Program |<br />
+-------------------+ +-------------------+----------------+<br />
| PC | | Target dsPic |<br />
+-------------------+ +------------------------------------+<br />
| COM PORT |=============| UART |<br />
+-------------------+ +------------------------------------+<br />
<br />
* '''Stage 1: User's Configuation'''<br />
**Select a COM port channel<br />
**Select a baudrate<br />
**Select the user hex file<br />
java -jar dsPicProgrammer.jar COM1 19200 foo.hex<br />
* '''Stage 2: Resetting Target Device'''<br />
**dsPicProgrammer sends a Break character (pull UART-TX to low logic, which is normally high).<br />
**User's program on dsPic detects the break character and reset the chip<br />
::NOTE: The user's program is expected to have the following code in order to enable this function. Otherwise, the target board must be restarted manually.<br />
void _ISR _U2RXInterrupt(void)<br />
{<br />
//No Framming error<br />
if( U2STAbits.FERR == 0)<br />
{<br />
//Normal procedure<br />
}<br />
//Framming error<br />
else<br />
{<br />
if ( U2STAbits.URXDA ){<br />
unsigned char data;<br />
data = (unsigned char) U2RXREG;<br />
if(data == 0x00){<br />
// A break char has been received: <br />
// U2RX has been pulled to zero for more than 13 bits<br />
// This is used to reboot the pic<br />
mdelay(800); //wait for break character to clear<br />
asm("reset"); //software reset<br />
}<br />
} <br />
}<br />
_U2RXIF = 0; //Clear the flag<br />
}<br />
* '''Stage 3: Entering Ingenia's Protocol'''<br />
** Transmission is conducted in 8N1, i.e. 8-bit, no parity, 1 stop-bit<br />
** Communication Protocol is reviewed in [http://www.ingenia-cat.com/reference/pdf/iBL.UG.V1.2.pdf ingenia bootloader user's guide] section 2.1.3. The following summarises the key steps on the PC side (Refer also to section 2.2.2).<br />
::#Autobaud rate detection: dsPicProgrammer continuously sends a character "U" [0x55] via COM port and waits for an acknowledgment character "U", [ACK] = [0x55]<br />
::#Version Control: dsPicProgrammer sends the command character [0x03]. On success, dsPicProgrammer receives 3 characters i) Major Version ii) Minor Version iii) Acknowledgment [0x55]<br />
::#Device ID Monitoring: dsPicProgrammer sends the read command character [0x01] + 24-bit address [High][Medium][Low] (0xFF0000). Then, it receives 4-byte data [High][Medium][Low][ACK]<br />
::#Load the user hex file and check integrity<br />
::#Start Programming: dsPicProgrammer issues the write command character [0x02] + 24-bit address [High][Medium][Low]+ Number of bytes [N] + [data 0] + [data 1] + ... + [data N-1] + [CRC]=(INTEL HEX8 Checksum - Sum modulo 256) and receives [ACK] or [NACK] = [0xFF]<br />
::NOTE: Writing is in row mode access (i.e. erase and write a whole row, each row has 32 instructions, or 96 bytes because each instruction has 24 bits)<br />
* '''Stage 4: Goto User's Program'''<br />
**dsPicProgrammer sends the goto user code command [0x0F]<br />
<br />
<br />
==USB-RS232 Bridge==<br />
<br />
*As USB ports are becoming more and more common, COM ports and Parallel ports may be redundant in the next few years. This section explore the possibilities of programming the target board through a USB port.<br />
*There are two options:<br />
#Use an external USB/RS232 adaptor, the driver will emulate a virtual COM port, such as [http://www.prolific.com.tw/eng/downloads.asp?ID=31 Prolific] and [http://www.ftdichip.com/Drivers/VCP.htm FDTI]. Ingenia has tested its bootloader with some USB-232 manufacturers (silabs, FTDI, etc..). However, the programming failed with our Prolific adapter. Application program may use [http://java.sun.com/products/javacomm/ JavaComm API] (javax.comm) and/or [http://www.rxtx.org/ RXTX] to drive the COM port.<br />
#Modified the bootloader program on PC to support USB communication. e.g. using [http://jusb.sourceforge.net/ jUSB] and [http://javax-usb.org/ JSR-80] (javax.usb). External circuits such as PIC18F4550 and MAX232 are required.<br />
<br />
|--User's App.--|-------Device Manager------|-------USB-RS232 Interface------|---dsPIC---|<br />
Option 1:<br />
+-------------+ +----------+ +----------+ +---+ +------------+ +-----+ +--------+<br />
| Application |--| JavaComm |--| Virtual |==|USB|--| FDTI |--|RS232|==| Target |<br />
| Program | | RXTX | | COM Port | +---+ | Circuitary | +-----+ | Board |<br />
+-------------+ +----------+ +----------+ +------------+ +--------+<br />
Option 2:<br />
+-------------+ +--------+ +---+ +------------+ +-----+ +--------+<br />
| Application |----------| JSR-80 |==========|USB|--| PIC18F4550 |--|RS232|==| Target |<br />
| Program | | jUSB | +---+ | MAX232 | +-----+ | Board |<br />
+-------------+ +--------+ +------------+ +--------+<br />
<br />
*Currently, when RXTX is incorporated with JavaComm API, operating systems supported include Linux, Windows, Mac OS, Solaris and other operating systems. On the other hand, jUSB and JSR-80 only works for linux.<br />
<br />
===FDTI Chipset===<br />
*FT232RL communicates with PC via USB to provide 1 UART channel.<br />
*Datasheet can be downloaded [http://www.ftdichip.com/Documents/DataSheets/DS_FT232R.pdf here]. <br />
**Refer to Fig. 11 (Page 19) for Bus Powered Configuration.<br />
**Refer to Fig. 16 (Page 24) for for UART TTL-level Receive [RXD -> 1], Transmit [TXD -> 4], Transmit Enable [CBUS2/TXDEN -> 3]. Omit Receive Enable [CBUS3/PWREN#] and use [CBUS2/TXDEN -> 2] <br />
**Refer to Fig. 15 (Page 23) for LED Configuration: [CBUS0/TXLED#] and [CBUS1/RXLED#]<br />
*Virtual COM Port Drivers can be downloaded [http://www.ftdichip.com/Drivers/VCP.htm here].<br />
<br />
<br />
==Programming the Device==<br />
<br />
===Requirements===<br />
*Hardware<br />
#PC with COM port (Windows XP Installed for MPLAB)<br />
#ICD2 Programmer<br />
#Target Board<br />
#5V Power Supply<br />
<br />
*Software<br />
#[http://ww1.microchip.com/downloads/en/DeviceDoc/MP750.zip MPLAB IDE v7.50]: v7.60 is not compatible with our current [http://www.sure-electronics.com/ ICD2 Programmers]. There are consistent "Devices cannot be founded" warnings.<br />
#[http://chungyan5.no-ip.org/websvn/listing.php dsPicProgrammer] ('''dsPicProgrammer.jar''')<br />
#[http://users.frii.com/jarvi/rxtx/download.html RXTX driver]: download and upzip rxtx-2.1-7-bins-r2.zip (Final)<br />
<br />
*Files<br />
#[http://chungyan5.no-ip.org/websvn/listing.php dsPicBootloader] ('''bl_5011.hex'''). Original assembly code by ingenia can be downloaded from [http://www.ingenia-cat.com/download/iBL.s here].<br />
#Application hex file (e.g. '''app.hex''')<br />
<br />
===Loading Bootloader (Once only)===<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 9.1 Loading Bootloader<br />
! Step !! Remarks <br />
|-valign="top"<br />
| Install [http://ww1.microchip.com/downloads/en/DeviceDoc/MP750.zip MPLAB IDE] || <br />
*Do '''NOT''' connect ICD 2 (via USB) to PC<br />
*Execute '''MPLAB vX.XX Install.exe'''<br />
|-valign="top"<br />
| Install USB Driver ||<br />
*Follow the instruction in (C:\Program Files\Microchip\MPLAB IDE\ICD2\Drivers\Ddicd2.htm)<br />
|-valign="top"<br />
| Select Target Chip ||<br />
*Run MPLAB IDE on PC<br />
*Select: Configure>Select Devices...<br />
*Choose dsPIC30F5011<br />
|-valign="top"<br />
| Target <-> ICD 2 ||<br />
*Use six pin cable. Beware of the pin assignments. Only pin 1 - 5 should be used.<br />
*Place Jumper on target board (if any). The Jumper connects target V<sub>cc</sub> to ICD 2.<br />
*Do '''NOT''' power-up the target.<br />
|-valign="top"<br />
| ICD 2 <-> PC ||<br />
*Plug-in ICD 2 to PC via USB cable<br />
*Power-up the target.<br />
*Select: Programmer>Select Programmer>MPLAB ICD 2<br />
*If this is the first time the ICD 2 is connected to PC, MPLAB IDE will automatically download the required OS to ICD 2, wait until it has finished<br />
*If you have not connected and powered up the target, you might see Warnings on invalid device IDs, and/or running self tests.<br />
*See results of self test if necessary: Programmer>Settings, Status Tab. Refer to [http://ww1.microchip.com/downloads/en/DeviceDoc/51331B.pdf ICD2 User's Guide] Chapter 7.<br />
|-valign="top"<br />
| Load Bootloader ||<br />
*Select: File>Import...<br />
*Select '''bl_5011.hex'''<br />
|-valign="top"<br />
| Start Programming ||<br />
*Select: Programmer>Program<br />
|-valign="top"<br />
| Finishing ||<br />
*Power-down the Taget<br />
*Select: Programmer>Select Programmer>None<br />
*Unplug USB cable<br />
|-<br />
|}<br />
<br />
===Loading Firmware===<br />
<!--using Firefox-File-Page_Setup-Format-Scale-85% to print --><br />
====Java Environment Setup====<br />
*Download and install the latest JDK or JRE<br />
**Available from [http://java.sun.com/javase/downloads/index.jsp Sun Microsystems] (e.g. JDK 6 Update 3)<br>[[Image:1 1 java.JPG]]<br><br />
*Download and Extract RXTX Driver <br />
**Available from [http://users.frii.com/jarvi/rxtx/download.html RXTX] <br />
**File: rxtx-2.1-7-bins-r2.zip (Final)<br />
**Extract the files using software such as WinRAR<br>[[Image:1 2 rxtx.JPG]]<br><br />
*Copy RXTXcomm.jar<br />
**To C:\Program Files\Java\X\lib\ext (under the latest jre, e.g. X = jre1.6.0_03)<br>[[Image:1 3 rxtxcomm.JPG]]<br><br />
*Copy rxtxSerial.dll<br />
**To C:\Program Files\Java\X\bin (under the lastest jre, e.g. X = jre1.6.0_03)<br />
**For Linux users, copy librxtxSerial.so to /jre/lib/[machine type] (i386 for instance)<br>[[Image:1 4 rxtxserial.JPG]]<br><br />
*Download dsPicProgrammer <br />
**Available from [http://chungyan5.no-ip.org/vc here]<br />
**Expand the latest tag under dsPicProgrammer<br />
**File: dsPicProgrammer.jar<br>[[Image:1 5 dspicprogrammer.JPG]]<br><br />
**Save the file (dsPicProgrammer.jar) and your hex file (foo.hex) to your local directory (e.g. C:\dsPicProgrammer\)<br>[[Image:1 6 dspicprogrammer2.JPG]]<br><br />
=====directly download this [http://chungyan5.no-ip.org/open_data/electronic_computer/platforms/dspic/dsPicProgrammer/dsPicProgrammer1.5.2.zip package]=====<br />
<br />
====Download Firmware====<br />
*Start a Command Prompt<br />
**Start -> Run<br>[[Image:2 1 run.JPG]]<br><br />
**Enter cmd<br>[[Image:2 2 cmd.JPG]]<br><br />
*Run dsPicProgrammer<br />
**Make sure your device is connected through a "Direct RS232 Cable" to PC Serial Port. <br />
**Change to the directory where dsPicProgrammer.jar is located and run the command:<br />
***[path/to/java/]java -Djava.library.path=[path/to/rxtxlib] -jar dsPicProgrammer.jar COM1 57600 foo.hex<br />
****for example, jre\bin\java -Djava.library.path=.\rxtx\bin -jar dspicProgrammer.jar COM1 57600 foo.hex<br />
***Or directly using dsPicProgrammer.bat COM1 57600 foo.hex(Windows)<br />
***java -jar dsPicProgrammer.jar /dev/ttyS0 57600 foo.hex (Linux)<br />
:::where COM1 is your COM Port ID<br />
:::57600 is communication speed [in bps]<br />
:::foo.hex is your firmware new file<br />
::[[Image:2 3 command.JPG]]<br />
**When the program prompt you for an input, press y:<br>[[Image:2 4 prompt.JPG]]<br><br />
**If communication can be established, you should see something like this:<br>[[Image:2 5 progress.JPG]]<br><br />
**Wait until programming is completed.<br>[[Image:2 6 complete.JPG]]<br><br />
**after all completed, power OFF your device, then power ON again, enjoy your new updated.<br />
<br />
====Troubleshooting====<br />
*Invalid COM Port<br />
**In case of selecting an invalid COM port, you should see the error message:<br>gnu.io.NoSuchPortException: Choosing COM Port Error<br>[[Image:3 1 com err.JPG]]<br><br />
*Missing firmware file<br />
**In case of selecting a firmware file that does not exist, you should see the error message:<br>java.io.FileNotFoundException: foo1.hex <The system cannot find the file specified><br>[[Image:3 2 file err.JPG]]<br><br />
*Missing RXTX driver<br />
**In case of missing the RXTX driver, you should see the error message:<br>Exception in thread “main” java.lang.NoClassDefFoundError: gnu/io/UnsupportedCommOperationException<br>[[Image:3 3 rxtx err.JPG]]<br><br />
<br />
==Remote Access==<br />
*At the moment, local devices (e.g. EEPROM, ADC, DAC, etc.) can only be accessed locally through POSIX functions such as open(), read(), write(), ioctl().<br />
*However, a client may need to access these devices on a remote server. This section reviews the background and gives some ideas on its possible implementation.<br />
<br />
===Requirements===<br />
*A remote file access protocol, to transfer "files" (i.e. device's data) such as:<br />
#[http://en.wikipedia.org/wiki/FTP File Transfer Protocol] (FTP): Required files are copied from sever to client for manipulation<br />
#[http://en.wikipedia.org/wiki/Remote_Shell Remote Shell] (RSH): Required files are copied from sever to client for manipulation<br />
#[http://en.wikipedia.org/wiki/Network_File_System_%28Sun%29 Network File System] (NFS): Required files are manipulated on sever<br />
*An API to access files using a selected protocol, such as:<br />
#[http://www.die.net/doc/linux/man/man2/lam_rfposix.2.html lam_rfposix]: A POSIX-like remote file service for Local Area Multicomputer<br />
#API employed by VxWorks: [http://en.wikipedia.org/wiki/VxWorks VxWorks] is a Unix-like real-time operating system, commonly used for embedded systems.<br />
<br />
===API Reference for VxWorks===<br />
*Reference:<br />
**[http://www.windriver.com/vxworks/ VxWorks Official Website]<br />
**[http://www-cdfonline.fnal.gov/daq/commercial/ OS Libraries API Reference]<br />
*Related Libraies<br />
**netDrv (netDrv.h): an API using FTP or RSH<br />
**nfsDrv (nfsDrv.h): an API using NFS<br />
<br />
<br />
==Conversion to dsPIC33F Devices==<br />
*This section discusses the conversion required from dsPIC30F5011 to dsPIC33FJ128GP306.<br />
*Refer to official document [http://ww1.microchip.com/downloads/en/DeviceDoc/70172A.pdf dsPIC30F to dsPIC33F Conversion Guidelines] (DS70172A).<br />
*Note that this section does not mainly intend to introduce the new functionalities of dsPIC33F devices. It only serves the purpose to summarise the major (if not minimum) changes required to port the setup of dsPIC30 to dsPIC33 devices.<br />
<br />
===Hardware===<br />
*dsPIC33 operates at voltage of 3.3V. A voltage regulator, such as [http://www.national.com/ds.cgi/LM/LM3940.pdf LM3940] can be used to convert 5V supply to 3.3V.<br />
*A 1uF capacitor has to be placed at pin 56 (previously V<sub>SS</sub>, now V<sub>DDCORE</sub>).<br />
<br />
===Software===<br />
<br />
====Configuration Bits====<br />
<br />
----<br />
*dsPIC33 can operate at 40MIPs at maximum. To configure the device using internal FRC, replace the configuration bits setting as follows:<br />
_FOSCSEL(FNOSC_FRCPLL); // FRC Oscillator with PLL<br />
_FOSC(FCKSM_CSDCMD & OSCIOFNC_ON & POSCMD_NONE); <br />
// Clock Switching and Fail Safe Clock Monitor is disabled<br />
// OSC2 Pin Function: OSC2(RC15) as Digital IO<br />
// Primary Oscillator Mode: Disabled<br />
_FWDT(FWDTEN_OFF); // Watchdog Timer Enabled/disabled by user software <br />
*Configure on-chip PLL at runtime as follows (at start of main function):<br />
_PLLDIV = 38; // M=40: PLL Feedback Divisor bits<br />
CLKDIV = 0; // N1=2: PLL VCO Output Divider Select bits<br />
// N2=2: PLL Phase Detector Input Divider bits<br />
OSCTUN = 22; // Tune FRC oscillator, if FRC is used; <br />
// 0: Center frequency (7.37 MHz nominal)<br />
// 22: +8.25% (7.98 MHz)<br />
RCONbits.SWDTEN = 0; // Disable Watch Dog Timer<br />
while(OSCCONbits.LOCK != 1); // Wait for PLL to lock<br />
<br />
====UART====<br />
<br />
----<br />
*No change is required.<br />
<br />
====I2C====<br />
<br />
----<br />
*dsPIC33 supports upto 2 I<sup>2</sup>C devices. As a result, replace all I<sup>2</sup>C related registers with xxI2Cyy to xxI2C'''1'''yy. For examples:<br />
_SI2C1IF = 0; //Clear Slave interrupt<br />
_MI2C1IF = 0; //Clear Master interrupt<br />
_SI2C1IE = 0; //Disable Slave interrupt<br />
_MI2C1IE = 0; //Disable Master interrupt<br />
I2C1BRG = I2C_BRG; // Configure Baud rate<br />
I2C1CONbits.I2CEN = 1;<br />
...<br />
etc.<br />
<br />
====ADC====<br />
<br />
----<br />
*The ADC in dsPic33 is significantly different from that in dsPic30. Specifically, ADC in dsPic33 uses DMA to buffer the adc data. Replace the open, interrupt routine, add and remove codes as follows:<br />
<br />
unsigned int adc_bufA[ADC_MAX_CH] __attribute__((space(dma),aligned(256)));<br />
unsigned int adc_bufB[ADC_MAX_CH] __attribute__((space(dma),aligned(256)));<br />
unsigned int* ADC16Ptr; //Pointer to ADC register buffer, <br />
unsigned char adc_ch_select = 0; //Pointer to channel to be read from<br />
unsigned char adc_data_ready = 0; //Indicate if RAM data is ready for output<br />
unsigned int which_dma = 0; //indicate which adc_buf to be used<br />
<br />
void adc_open(void)<br />
{<br />
// Configure interrupt<br />
_AD1IF = 0; //clear ADC interrupt flag<br />
_AD1IE = 0; //disable adc interrupt<br />
AD1CHSbits.CH0NA = 0;<br />
// Configure analog i/o <br />
_TRISB0 = 1;<br />
_TRISB1 = 1; <br />
AD1PCFG = 0xFFFC; //Enable AN0 (Vref+) and AN1 (Vref-)<br />
AD1PCFGH = 0xFFFF; //AN16-AN31: Disabled<br />
// Configure scan input channels <br />
AD1CSSL = 0x0003; //0 => Skip, 1 => Scan<br />
AD1CSSH = 0x0000; //Skipping AN16-AN31<br />
// ADCCON4:<br />
AD1CON4bits.DMABL = 0; // Each buffer contains 1 word<br />
// ADCCON3:<br />
AD1CON3bits.SAMC = 1; //1TAD for sampling time<br />
AD1CON3bits.ADRC = 0; //Use system clock<br />
AD1CON3bits.ADCS = ADC_ADCS; //each conversion requires 14TAD<br />
// ADCCON2:<br />
AD1CON2bits.VCFG = 3; //External Vref+, Vref-<br />
AD1CON2bits.CSCNA = 1; //Scan input<br />
AD1CON2bits.SMPI = 1; //2 channels are scanned<br />
// ADCCON1:<br />
AD1CON1bits.FORM = 0; //[0:integer]; [2 fractional]; [3 siged fractional]<br />
AD1CON1bits.SSRC = 7; //auto covert, using internal clock source<br />
AD1CON1bits.ASAM = 1; //auto setting of SAMP bit<br />
AD1CON1bits.AD12B = 1; //12-bit, 1-channel ADC operation<br />
AD1CON1bits.ADDMABM = 0; // DMA buffers are built in scatter/gather mode<br />
AD1CON1bits.ADON = 1; // Turn on the A/D converter<br />
// DMA0 Configuration:<br />
DMA0CONbits.AMODE = 2; // Configure DMA for Peripheral indirect mode<br />
DMA0CONbits.MODE = 2; // Configure DMA for Continuous Ping-Pong mode<br />
DMA0PAD=(int)&ADC1BUF0; <br />
DMA0CNT = 1; // generate dma interrupt every 2 samples <br />
// same as SMPI because only 1 dma buffer per channel <br />
DMA0REQ = 13; // Select ADC1 as DMA Request source<br />
DMA0STA = __builtin_dmaoffset(adc_bufA); <br />
DMA0STB = __builtin_dmaoffset(adc_bufB);<br />
_DMA0IF = 0; // Clear the DMA interrupt flag bit<br />
_DMA0IE = 1; // Set the DMA interrupt enable bit<br />
DMA0CONbits.CHEN=1; // Enable DMA<br />
}<br />
<br />
void _ISR _DMA0Interrupt(void)<br />
{<br />
ADC16Ptr = (which_dma == 0)? adc_bufA : adc_bufB; //Update pointer<br />
adc_data_ready = 1;<br />
which_dma ^= 1; //Next buffer to be used<br />
_DMA0IF = 0; //Clear the DMA0 Interrupt Flag<br />
}<br />
<br />
static void adcAdd(unsigned char ch){<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
TRISB = TRISB | mask;<br />
AD1CSSL = AD1CSSL | mask; <br />
AD1PCFG = ~AD1CSSL;<br />
AD1CON2bits.SMPI++; //take one more sample per interrupt<br />
DMA0CNT++; <br />
}<br />
<br />
static void adcRm(unsigned char ch){<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
AD1PCFG = AD1PCFG | mask;<br />
AD1CSSL = ~AD1PCFG;<br />
AD1CON2bits.SMPI--; //take one less sample per interrupt<br />
DMA0CNT--; <br />
}<br />
<br />
====EEPROM====<br />
<br />
----<br />
*There is no EEPROM in dsPIC33 devices. Please consider to use an external EEPROM using I<sup>2</sup>C communication.<br />
<br />
====Simple PWM====<br />
<br />
----<br />
*No change is required.<br />
<br />
===Memory Map for dsPIC33FJ128GP306===<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 11.1 Memory Location<br />
! Type !! Start Address !! End Address !! Size<br />
|-valign="top"<br />
| Flash || 0x000000 ||0x0157FF || 86K<sup>[1]</sup><br />
|-valign="top"<br />
| +--Flash: Reset Vector || 0x000000 ||0x000003 || 4<br />
|-valign="top"<br />
| +--Flash: Interrupt Vector Table || 0x000004 ||0x0000FF || 252<br />
|-valign="top"<br />
| +--Flash: Alternate Vector Table || 0x000104 ||0x0001FF || 252<br />
|-valign="top"<br />
| +--Flash: User Program || 0x000200 ||0x0157FF || 85.5K<br />
|-valign="top"<br />
| Programming Executive || 0x800000 || 0x800FFF || 4K<sup>[1]</sup><br />
|-valign="top"<br />
| Config Registers || 0xF80000 || 0xF80017 || 24<br />
|-valign="top"<br />
| Device ID (0xE5) || 0xFF0000 || 0xFF0003 || 4<br />
|-<br />
|}<br />
[1] Each address is 16-bit wide. Every two addresses correspond to a 24-bit instruction. Each even address contains 2 valid bytes; each odd address contains 1 valid byte plus 1 phathom byte.<br><br />
<br />
===Custom Linker Script to Maximize Space for Constant Data===<br />
*Constant data declared using keyword '''const''' will be stored in the .const section in the flash memory.<br />
*Normally, during compilation, the linker will assign these data after the program code (.text section).<br />
*Since .const is accessed by auto-psv function, to maximize the space for constant data (32kb), the .const section needs to be aligned at 0x80000 boundary.<br />
*This requires the following change in linker script:<br />
<br />
__CONST_BASE = 0x8000;<br />
<br />
.text __CODE_BASE :<br />
{<br />
*(.reset);<br />
*(.handle);<br />
*(.libc) *(.libm) *(.libdsp); /* keep together in this order */<br />
*(.lib*);<br />
/* *(.text); deleted to maximize space for const data */<br />
} >program<br />
<br />
.const __CONST_BASE :<br />
{<br />
*(.const);<br />
} >program<br />
<br />
*If your program is large, after this change in linker script, function calls may involve large jump in the memory map (>32kB). As a result, you may need to enable the large code and large memory model during compilation. In such case, use the following options in your build path:<br />
-mlarge-code -mlarge-data<br />
*Meanwhile, functions that are defined in the standard C libraries, but are replaced with your own implementations (e.g. I/O stubs: open(), read(), write(), lseek(), ioctl() etc.) may have the following linker error:<br />
/usr/pic30-elf/lib//libc-elf.a(fflush.eo)(.libc+0x3c): In function '.LM11':<br />
: Link Error: relocation truncated to fit: PC RELATIVE BRANCH _write<br />
/usr/pic30-elf/lib//libc-elf.a(fclose.eo)(.libc+0x42): In function '.LM18':<br />
: Link Error: relocation truncated to fit: PC RELATIVE BRANCH _close <br />
*To resolve the problem, you need to place the functions in the .libc section rather than in the .text section, like this:<br />
#define LIBC_CODE_LOC __attribute__ ( (section(".libc")))<br />
<br />
int LIBC_CODE_LOC open(const char *pathname, int flags){ ... }<br />
int LIBC_CODE_LOC close(int fd){ ... }<br />
int LIBC_CODE_LOC write(int fd, void* buf, int count) { ... }<br />
int LIBC_CODE_LOC read(int fd, void* buf, int count) { ... }<br />
int LIBC_CODE_LOC ioctl(int fd, int request, void* argp) { ... }<br />
int LIBC_CODE_LOC lseek(int fd, int offset, int whence) { ... }<br />
<br />
===dsPicBootloader and dsPicProgrammer===<br />
*RTSP for dsPIC33F is different from dsPIC30F.<br />
**Row size changes from 32 instructions (96bytes) to 64 instructions (192 bytes)<br />
**Erase operation changes from 1 row to 8 rows<br />
**No EEPROM<br />
*With regards to the above changes, dsPicBootloader and dsPicProgrammer has been modified. In particular, dsPicProgrammer can be used to program both dsPic30F and dsPic33F devices (Yet, dsPic33F is no longer compatible with Ingenia's programmer). You can easily add your devices to the source code.<br />
<br />
==Downloads==<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 12.1 Related software download links for dsPicBootloader and dsPicProgrammer<br />
! Program<br />
! Site 1<br />
! Site 2<br />
! Remarks<br />
|- valign="top"<br />
| JDK<br />
| [http://java.sun.com/javase/downloads/index.jsp website]<br />
| <br />
| Download latest JDK<br />
|- valign="top"<br />
| RXTX<br />
| [http://users.frii.com/jarvi/rxtx/download.html website]<br />
| <br />
| Download rxtx-2.1-7-bins-r2.zip or later<br />
|- valign="top"<br />
| dsPicBootloader<br />
| [http://chungyan5.no-ip.org/vc click]<br />
| [http://www.opencircuits.com/images/a/a7/DsPicBootloader_1_3_1.zip click (v1.3)]<br />
| Under "dsPicBootloader/", download bl_5011.s or bl_j128gp306.s<br />
|-valign="top"<br />
| dsPicProgrammer<br />
| [http://chungyan5.no-ip.org/vc click]<br />
| [http://www.opencircuits.com/images/9/9e/DsPicProgrammer_1_3_5.zip click (v1.3.5)]<br />
| Under "dsPicProgrammer/", dowload dsPicProgrammer.jar<br><br>Alternatively, if you want to compile yourself or modify the source code, download <br>all source files under "dsPicProgrammer/" '''plus''' RdFileIntelHex.java under <br>"IntelHexPaser/tags/0.02.00/".<br>You should also install RXTX on your local machine as recommended in the readme file.<br />
|- valign="top"<br />
| Ingenia's bootloader<br />
| [http://www.ingenia-cat.com/en/downloads.php website]<br />
| <br />
| Download original ingenia's bootloader<br />
|-<br />
|}<br />
<br />
==ToDo==<br />
*program the bootloader into flash under linux platform</div>Yanhttp://www.opencircuits.com/index.php?title=Ethernet_Module&diff=15630Ethernet Module2008-06-16T07:38:26Z<p>Yan: dhcp fault fr. buffalo router</p>
<hr />
<div>==Introduction==<br />
*This project aims to develop an Ethernet Module, to be used in conjunction with a 8/16 bits embedded system such as the [http://opencircuits.com/DsPIC30F_5011_Development_Board dsPic33F development board].<br />
*The entire Ethernet Module consists of:<br />
#Hardware: a LAN card based on [http://www.davicom.com.tw/eng/index.htm Davicom] DM9000A chip<br />
#Software: a TCP/IP stack based on [http://www.sics.se/~adam/uip/ uIP] 1.0 or [http://savannah.nongnu.org/projects/lwip/ lwIP]<br />
<br />
<br />
==Bug List==<br />
*dhcp client fault from buffalo router<br />
<br />
==ToDo List==<br />
<br />
<br />
==Hardware==<br />
===Component List===<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
! Special Item !! Description !! Quantity<br />
|-valign="top"<br />
| [http://www.davicom.com.tw/big5/download/Data%20Sheet/DM9000A-DS-F01-101906.pdf DM9000AEP] || Ethernet Controller || 1<br />
|-<br />
| [http://www.hanrun.com/hr/upfile/2_1_113.pdf HR911102A] || RJ45 Connector with Integrated Magnetics for 10/100 Base-TX || 1<br />
|-<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/21749F.pdf 93LC46B-I/SN] || 1K Serial EEPROM || 1 (Optional)<br />
|-<br />
| 25MHz Crystal || Crystal || 1<br />
|-<br />
| 22pF || For Crystal Use || 2<br />
|-<br />
| 220uF || For RXVDD25/TXVDD25 || 1<br />
|-<br />
| 49.9ohm || For RX+/RX-/TX+/TX- || 4<br />
|-<br />
| 6.8kohm || For BGRES/BGGND || 1<br />
|-<br />
| 510ohm || For LEDs|| 2<br />
|-<br />
|}<br />
<br />
===Circuit and PCB===<br />
in [http://chungyan5.no-ip.org/vc/?root=ethernet gEDA format]<br />
and its gEDA [http://www.opencircuits.com/PCB_Footprints#gEDA_Symbols_and_footprints sym and footprints]<br />
<br />
<br />
==Software Driver==<br />
*Download [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/dm9000a.c?root=freertos_posix&view=markup dm9000a.c]<br />
*Download [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/include/dm9000a.h?root=freertos_posix&view=markup dm9000a.h]<br />
*Base on [http://www.freertos.org/ FreeRTOS] and [http://opencircuits.com/DsPIC30F_5011_Development_Board dsPIC33 platform]<br />
*Using POSIX-like API:<br />
**'''int dmfe_open(int flags)''': initialize the Ethernet controller for 10MHz Half-Duplex<br />
**'''int dmfe_close()''': turn off the PHY layer<br />
**'''int dmfe_read(void)''': copy a packet to the default buffer<br />
**'''int dmfe_write(unsigned char device, unsigned char *buf, int count)''': copy count bytes of the data from buf and transmit<br />
**'''void dmfe_interrupt(void)''': process the transmit interrupt from DM9000A<br />
<br />
<br />
==TCP/IP Stack==<br />
*uIP and lwIP are light weight TCP/IP Stack designed for 8-bit/16-bit embedded systems.<br />
<br />
----<br />
<br />
===uIP===<br />
*Develped by Adam Dunkels of the Networked Embedded Systems group at the Swedish Institute of Computer Science.<br />
*uIP is under the [http://www.sics.se/~adam/uip/index.php/License BSD-style license]<br />
====CVS Repository====<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
! Attribute !! Value<br />
|-valign="top"<br />
| Host || uip-stack.cvs.sourceforge.net<br />
|-<br />
| Repository Path || /cvsroot/uip-stack<br />
|-<br />
| Connection Type || pserver<br />
|-<br />
| User || anonymous<br />
|-<br />
|}<br />
*Changes made to CVS Repository (tag: HEAD v1.1)<br />
**'''uip.c'''<br />
***Comment out all DEBUG_PRINTF(...) in lines 1, 323, 910, 1015, 1070, 1863, 1868, 1869<br />
**'''uip.h'''<br />
***Change line 1070 to<br># define HTONS(n) (u16_t)(((((u16_t) (n)) << 8)&0xff00) | ((((u16_t) (n)) >> 8)&0x00ff))<br />
**'''psock.c'''<br />
***Change line 188 to<br>s->sendptr = (u8_t*) buf;<br />
***Change lines 276, 303 to<br>buf_setup(&psock->buf, (u8_t*)(psock->bufptr), psock->bufsize);<br />
***Change line 334 to<br>buf_setup(&psock->buf, (u8_t*)buffer, buffersize);<br />
<br />
====Porting====<br />
*Include the following files to use the uIP stack<br />
**timer.c<br />
**uip.c<br />
**uip_arp.c<br />
**psock.c<br />
*The following files have been created to port uIP 1.0 to dsPic33F development board using FreeRTOS<br />
*[http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/clock-arch.c?root=freertos_posix&view=markup clock-arch.c]: return the os tick counts since the system is turned on.<br />
*[http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/include/clock-arch.h?root=freertos_posix&view=markup clock-arch.h]: a constant specifying the number of os ticks in one second.<br />
*[http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/dspic33/rackmount/04_uip/include/uip-conf.h?root=freertos_posix&view=markup uip-config.h]: configuration for your application.<br />
<br />
----<br />
<br />
===lwIP===<br />
*lwIP is a small independent implementation of uIP.<br />
*It is more powerful than uIP but requires more memory.<br />
*lwIP is under the [http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5 Modified BSD License]<br />
====CVS Repository====<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
! Attribute !! Value<br />
|-valign="top"<br />
| Host || cvs.savannah.nongnu.org<br />
|-<br />
| Repository Path || /sources/lwip<br />
|-<br />
| Connection Type || pserver<br />
|-<br />
| User || anonymous<br />
|-<br />
|}<br />
====Porting====<br />
*To be added<br />
<br />
<br />
==uIP Ethernet Application==<br />
<br />
===DHCP Client===<br />
*Enable UDP in "uip-config.h"<br />
#define UIP_CONF_UDP 1<br />
*Make sure your uip buffer size is large enough (DHCP messages from some servers can be more than 500 bytes). In my setting, I use 1536 in "uip-config.h"<br />
#define UIP_CONF_BUFFER_SIZE 1536<br />
*Include the dhcpc.h header file in "uip-config.h"<br />
#include "dhcpc.h"<br />
*Change PT_WAIT_UNTIL(...) to PT_YIELD_UNTIL(...) in line 259 and 276 in "dhcpc.c" [This is a known bug in dhcpc.c]<br />
*In your main loop, initialize your MAC address and DHCP if UIP_FIXEDADDR is 0 in "uip-opt.h", for example:<br />
int main(void)<br />
{<br />
uip_ipaddr_t ipaddr;<br />
struct timer periodic_timer, arp_timer;<br />
struct uip_eth_addr mac = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06};<br />
<br />
timer_set(&periodic_timer, CLOCK_SECOND / 2);<br />
timer_set(&arp_timer, CLOCK_SECOND * 10);<br />
<br />
tapdev_init();<br />
uip_init();<br />
<br />
uip_setethaddr(mac);<br />
dhcpc_init(&mac, 6);<br />
<br />
while(1){<br />
//normal codes goes here<br />
}<br />
}<br />
*Implement dhcpc_configured(). This function will be called after DHCP client has obtained an IP address. Basically, you have to at least set your IP address, subnet mask and default gateway, for example,<br />
void dhcpc_configured(const struct dhcpc_state *s)<br />
{<br />
uip_sethostaddr(s->ipaddr);<br />
uip_setnetmask(s->netmask);<br />
uip_setdraddr(s->default_router);<br />
<br />
//you can print your ip addr to your console/lcd to see if you get a valid ip address<br />
}<br />
*An example of using DHCP Client in the dsPic33F development board can be found [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/common/app_http.c?root=freertos_posix&view=markup here].<br />
<br />
===Web Server===<br />
*Include the "webserver.h" header file in "uip-config.h"<br />
#include "webserver.h"<br />
*Modify httpd-fs.h<br />
**HTTPD_FS_STATISTICS set to 0<br />
*Create a website using HTML tags with/without Javascript<br />
*Modify httpd-fs.c<br />
**changed #include "httpd-fsdata.c" to #include <httpd-fsdata.c> <br />
*Generate httpd-fsdata.c for your website by executing '''perl makefsdata''' under your web root directory.<br />
====add-on====<br />
*The Web Server included in uIP 1.0 has been designed to load/reload the entire page (either html/shtml files) in response to a HTTP GET command, e.g.<br />
GET /index.html HTTP/1.1<br />
GET /abc.shtml HTTP/1.1<br />
*As a result, if the webpage is required to refresh the dynamic data periodically, the surfing experience will be degraded by the large transfer of datastream.<br />
*In consideration of the above issue, a solution is proposed here, so that the webserver can handle this kind of cgi HTTP-request<br />
GET /abc.shtml?val=500.0&button=Set HTTP/1.1<br />
*Modify httpd.c<br />
**added #include "httpd-hget.h" in line 63<br />
**added httpd_hget(s->filename) in line 224<br />
*Create httpd-hget.h<br />
**added to generate dynamic pages, e.g. /abc.shtml?button=Refresh<br />
#ifndef __HTTPD_HGET_H__<br />
#define __HTTPD_HGET_H__<br />
extern void httpd_hget(char *name);<br />
#endif<br />
*Create httpd-hget.c<br />
**an example is shown [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/dspic33/rackmount/04_uip/uip/httpd-hget.c?root=freertos_posix&view=markup here]<br />
<br />
==SNMP Agent==<br />
*Simple Network Management Protocol (SNMP) is a standard protocol to access variables to remote device via the Internet.<br />
*It belongs to the Application Layer, as in HTTP.<br />
*If a device is SNMP compatible, any SNMP compatible host system can monitor and control that device.<br />
<br />
===Components in a SNMP System===<br />
*Network Management Station (NMS)<br />
**This is a client, initiating SNMP communication.<br />
**This can be a PC with an NMS software (e.g. [http://nino.sourceforge.net/nino/index.html NINO]), polling data from the SNMP agents periodically.<br />
*SNMP Agents<br />
**These are servers, responding to one or multiple NMS requests.<br />
*Management Information Base (MIB)<br />
**A special collection of variables managed by the SNMP agents.<br />
**MIB has a tree-like structure.<br />
**An Object Identifier (OID) is given for each node.<br />
**Data are stored at the end-nodes.<br />
**Private variables may be constructed under the "enterprise" sub-tree.<br />
**The OID for "enterprise" can be obtained from [http://www.iana.org/cgi-bin/enterprise.pl Internet Assigned Number Authority (IANA)].<br />
<br />
===Abstract Syntax Notation===<br />
*Each MIB variable contains several attributes, such as data type, access type and object identifier.<br />
*Abstract Syntax Notation version 1 (ASN.1) is a language to define these attributes in SNMP.<br />
<br />
<br />
==Architecture==<br />
<pre><nowiki><br />
+------------------------------------+<br />
| application |<br />
| |<br />
+--------+--------+---------+--------+<br />
| web | dhcp | snmp | ... |<br />
| Server | | | |<br />
| | | | |<br />
|--------+--------+---------+--------+<br />
| ethernet | uip |<br />
| control | |<br />
+-----------------+------------------+<br />
| driver |<br />
+------------------------------------+<br />
</nowiki></pre><br />
<br />
<br />
==Reference==<br />
===DM9000A===<br />
*[http://www.davicom.com.tw/eng/products/dm9000a.htm DM9000A Description]<br />
*[http://www.davicom.com.tw/big5/download/Data%20Sheet/DM9000A-DS-F01-101906.pdf DM9000A Datasheet]<br />
*[http://www.davicom.com.tw/big5/download/AC/dm9000a/DM9000A%20circuit_EMI_052306.pdf Application Circuit]<br />
*[http://www.davicom.com.tw/big5/download/LayoutGuide/DM9000A_9010-LG-V11_031706.pdf Layout Guidelines]<br />
*[http://www.davicom.com.tw/big5/download/ApplicationNote/DM9000A%20Application%20Notes%20Ver%201_20_101906.pdf Application Note]<br />
*[http://www.davicom.com.tw/eng/download/Driver/driver_9000.htm DM9000A Official Drivers]<br />
===dsPic33F Development Board===<br />
*[http://opencircuits.com/DsPIC30F_5011_Development_Board dsPic33F Development Board]<br />
===uIP===<br />
*[http://www.sics.se/~adam/uip/index.php/Main_Page uIP Description]<br />
*[http://www.sics.se/~adam/uip/index.php/Documentation uIP Documentation]<br />
*[http://www.sics.se/~adam/uip/index.php/Download Download]<br />
*[http://sourceforge.net/cvs/?group_id=186227 CVS Repository]<br />
===lwIP===<br />
*[http://savannah.nongnu.org/projects/lwip/ lwIP Description]<br />
*[http://www.nongnu.org/lwip/ Documentation]<br />
===HTML===<br />
*[http://www.w3schools.com/default.asp W3 Schools]: Learning how to write HTML and JavaScript<br />
*[http://www.nvu.com/index.php Nvu]: Open source HTML Editor<br />
===SNMP===<br />
*[http://www.snmplink.org SNMP Link]: Information on SNMP Agents<br />
*[http://pen.iana.org/pen/PenApplication.page IANA]: Applying a Private Enterprise Number</div>Yanhttp://www.opencircuits.com/index.php?title=DsPIC30F_5011_Development_Board&diff=15623DsPIC30F 5011 Development Board2008-06-12T11:03:23Z<p>Yan: /* Loading Firmware */ keep the dspic programmer package which contains the java and rxtx drv</p>
<hr />
<div>==Introduction==<br />
<br />
===Features of dsPIC30F5011===<br />
*2.5 to 5V <br />
*Up to 30MIPs<br />
*High current/sink source I/O pins: 25mA<br />
*DSP Instruction Set<br />
*Dual programming techniques: ICSP and RTSP<br />
*UART: up to 2 modules<br />
*I<sup>2</sup>C: up to 1Mbps<br />
*10-bit A/D, 1.1 Msps <br />
*12-bit A/D, 200 ksps<br />
*44K flash (66Kb), 4Kb RAM, 1Kb EEPROM<br />
*No DAC<br />
*Pin-to-pin compatible with other dsPICs<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 1.1 Comparison with Compatible dsPICs<br />
! dsPic !! Price<br>US$ !! MIPs<br />
! Flash<br>(kB)!! RAM<br>(kB) !! EEPROM<br>(kB)<br />
! I/O !! ADC<br>12-bit !! IC !! OC !! Motor<br>Ctrl !! Timers<br />
! QEI !! UART !! SPI !! I2C !! CAN !! Codec<br />
|- <br />
| 30F5011 || 5.91 || 30<br />
| 66 || 4 || 1<br />
| 52 || 16 || 8 || 8 || 0 || 5x16bit<br>2x32bit<br />
| 0 || 2 || 2 || 1 || 2 || 1<br />
|-<br />
| 30F6011A || 7.73 || 30<br />
| 132 || 6 || 2<br />
| 52 || 16 || 8 || 8 || 0 || 5x16bit<br>2x32bit<br />
| 0 || 2 || 2 || 1 || 2 || 0<br />
|-<br />
| 30F6012A || 7.85 || 30<br />
| 144 || 8 || 4<br />
| 52 || 16 || 8 || 8 || 0 || 5x16bit<br>2x32bit<br />
| 0 || 2 || 2 || 1 || 2 || 1<br />
|- <br />
| 33FJ128GP206 || 4.62 || 40<br />
| 128 || 8 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 1 || 0 || 1<br />
|-<br />
| 33FJ128GP306 || 4.81 || 40<br />
| 128 || 16 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 2 || 0 || 1<br />
|-<br />
| 33FJ128GP706 || 5.49 || 40<br />
| 128 || 16 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 2 || 2 || 1<br />
|-<br />
| 33FJ128MC506 || 4.97 || 40<br />
| 128 || 8 || 0<br />
| 53 || 16 || 8 || 8 || 8 || 9x16bit<br>4x32bit<br />
| 1 || 2 || 2 || 2 || 1 || 0<br />
|-<br />
| 33FJ128MC706 || 5.38 || 40<br />
| 128 || 16 || 0<br />
| 53 || 16 || 8 || 8 || 8 || 9x16bit<br>4x32bit<br />
| 1 || 2 || 2 || 2 || 1 || 0<br />
|-<br />
| 33FJ256GP506 || 6.11 || 40<br />
| 256 || 16 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 2 || 1 || 1<br />
|-<br />
|}<br />
<br />
===Web Page===<br />
*[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2529&param=en024856 Microchip Official Website]<br />
<br />
===Forum===<br />
*[http://direct.forum.microchip.com/default.aspx Microchip]: Official forum by Microchip<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=49 MPLAB ICD 2]: Subforum on ICD 2 programmer<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=57 MPLAB IDE]: Subforum on IDE<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=101 MPLAB C30 Compiler, ASM30, Link30 forum]: Subforum on C compiler. Refer to [http://ww1.microchip.com/downloads/en/DeviceDoc/C30_Users_Guide_51284e.pdf MPLAB C30 C Compiler User's Guide] Chapter 3<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=153 dsPIC30F Topics]: Subformum on dsPIC30F<br />
*[http://www.gnupic.org/ GNUPIC]: Discussion on PIC in Linux Systems<br />
**[http://www.linuxhacker.org/cgi-bin/ezmlm-cgi?1:dds:5443#b Debian]<br />
*[http://www.htsoft.com/forum/all/ubbthreads.php/Cat/0/C/6 HI-TECH Software Forum]: Discussion on dsPICC, a C compiler developed by HI-TECH<br />
*[http://piclist.com/techref/piclist/index.htm PICList]: Discussion on older PIC systems (not dsPIC)<br />
*[http://groups.google.com/group/pickit-devel PicKit]: Discussion on PICkit/PICkit 2 programmers<br />
*[http://sourceforge.net/forum/forum.php?forum_id=382005 FreeRTOS Real Time Kernel]: Open Discussion and Support on FreeRTOS <br />
<br />
===References===<br />
*dsPIC30F<br />
**[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2574 dsPIC30F Family Reference Manual Sections]: Contains detailed descriptions on dsPIC30F register definitions and example codes<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80169E.pdf dsPIC30F Family Reference Manual Errata (Use with revision 70046B only)]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70116F.pdf dsPIC30F5011, dsPIC30F5013 Data Sheet]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80210e.pdf dsPIC30F5011/5013 Rev. A1/A2 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80223D.pdf dsPIC30F5011/5013 Rev. A3 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70102G.pdf Flash Programming Specification]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70157B.pdf dsPIC30F Programmer's Reference Manual]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80170a.pdf dsPIC30F Programmer's Reference Manual Errata (use with revision DS70030E only)]<br />
<br />
*dsPIC33F<br />
**[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2573 dsPIC33F Family Reference Manual Sections]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70165E.pdf dsPIC33F Family Data Sheet]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80279B.pdf dsPIC33F Rev. A2 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80306A.pdf dsPIC33FJXXXGPX06/X08/X10 Rev. A2 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70152C.pdf Flash Programming Specification]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70172A.pdf dsPIC30F to dsPIC33F Conversion Guidelines]<br />
*ICD2 Programmer<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/51331B.pdf ICD2 User's Guide] <br />
*MPLAB<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/51519B.pdf MPLAB IDE User's Guide]<br />
*C30 Compiler<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/C30_Users_Guide_51284e.pdf MPLAB C30 C Compiler User's Guide]: Contains commands for using pic30-elf-gcc <br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/16bit_Language_Tool_Libraries_51456c.pdf 16-bit Language Tools Libraries]: Contains summaries and examples of using DSP libraries, standard C libraries and device libraries<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/Asm30_Link_Util_51317e.pdf MPLAB ASM30, MPLAB LINK30 and Utilities User's Guide]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/51322d.pdf dsPIC30F Language Tools Quick Reference Card]<br />
<br />
===Code Examples===<br />
*[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1408 Microchip Example Codes for dsPic]<br />
<br />
<br />
==Programming Methods==<br />
*There are 2 programming methods: In-Circuit Serial Programming (ICSP) and Run-Time Self-Programming (RTSP)<br />
*ICSP allows the devices to be programmed after being placed in a circuit board.<br />
*RTSP allows the devices to be programmed when an embedded program is already in operation.<br />
<br />
===ICSP: External Programmer (ICD2)===<br />
*Two types of ICSP are available: '''ICSP''' and '''Enhanced ICSP'''. Both of them require setting MCLR# to V<sub>IHH</sub> (9V – 13.25V).<br />
*Standard ICSP<br />
**Use external programmer (e.g. MPLAB<sup>®</sup> ICD 2, MPLAB<sup>®</sup> PM3 or PRO MATE<sup>®</sup> II) only.<br />
**Required low-level programming to erase, program and verify the chip.<br />
**Slower, because codes are serially executed.<br />
**Program memory can be erased using ''Normal-Voltage'' (4.5 – 5.5V) or ''Low-Voltage'' (2.5V – 4.5V).<br />
<br />
*Enhanced ICSP<br />
**Use external programmer and '''Programming Executive''' (PE).<br />
**PE is stored in the on-chip memory.<br />
**PE allows faster programming.<br />
**PE can be downloaded to the chip by external programmer using the standard ICSP method.<br />
**PE contains a small command set to erase, program and verify the chip, avoiding the need of low-level programming.<br />
<br />
====Hardware Interface====<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.1 Pin Used by ICSP<br />
! Pin Label !! Function !! Pin Number<br />
|- <br />
| MCLR# || Programming Enable|| 7<br />
|-<br />
| V<sub>DD</sub> || Power Supply || 10, 26, 38, 57<br />
|-<br />
| V<sub>SS</sub> || Ground || 9, 25, 41, 56<br />
|- <br />
| PGC || Serial Clock || 17<br />
|-<br />
| PGD || Serial Data || 18<br />
|-<br />
|}<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.2 Available Programmers in the Market<br />
! Product Name<br />
! Interface with PC<br />
! Interface with Device<br />
! Price (US)<br />
! Postage (US)<br />
! Total (US)<br />
|- <br />
| [http://direct.www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en010046&part=DV164005 MPLAB<sup>®</sup> ICD 2]<br />
| USB or RS232<br />
| [http://www.microchip.com/Microchip.WWW.SecureSoftwareList/secsoftwaredownload.aspx?device=en010046&lang=en&ReturnURL=http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en010046&part=DV164005# 6-PIN RJ-12 connector]<br />
| $159.99<br />
| -<br />
| -<br />
|-<br />
| [http://www.etekronics.com/product_info.php?cPath=24&products_id=48 Full Speed USB Microchip ICD2<br> Debugger and Programmer]<br />
| USB<br />
| 6-PIN ICSP connector<br>6-PIN RJ-12 connector<br />
| $72.00<br />
| $12.00<br />
| $84.00<br />
|-<br />
| [http://www.etekronics.com/product_info.php?cPath=24&products_id=47 Mini Microchip Compatible ICD2<br> Debugger and Programmer]<br />
| RS232<br />
| 6-PIN ICSP connector<br>6-PIN RJ-12 connector<br />
| $45.00<br />
| $10.00<br />
| $55.00<br />
|-<br />
| [http://www.inexglobal.com/microcontroller.php ICDX30]<br />
| RS232<br />
| 6-pin RJ-11<br />
| $51.00<br />
| $47.46<br />
| $98.46<br />
|-<br />
| *[http://www.sure-electronics.net Clone Microchip ICD2] (Now Using)<br />
| USB<br />
| 6-pin flat cables<br />
| $30.00<br />
| $12.00<br />
| $42.00<br />
|-<br />
|}<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.3 DIY ICD 2 Programmer Circuit<br />
! Source !! Schematic !! PIC16F877A Bootloader<br />
|- <br />
| [http://membres.lycos.fr/silicium31/Electronique/PIC/FreeIcdEnglish.htm Patrick Touzet]<br />
| [http://membres.lycos.fr/silicium31/Electronique/PIC/ICD2%20V1.3.pdf Yes]<br />
| [http://membres.lycos.fr/silicium31/Electronique/PIC/ICD2_FW.zip HEX]<br />
|-<br />
| [http://www.nebadje.org/doku.php?id=neblab:icd2clone Nebadje]<br />
| [http://people.ee.ethz.ch/~jbiveron/nebadje/ICD2_DOC.pdf Yes]<br />
| [http://people.ee.ethz.ch/~jbiveron/nebadje/ICD2_FW.zip Zip]<br />
|-<br />
|}<br />
<br />
====Software Interface====<br />
*The program can be written and compiled in an Integrated Development Environment (IDE) using either Assembly or C. The complied codes are then loaded to the device through the external programmer.<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.4 Summary of IDE<br />
! Product Name !! Features !! OS !! Price (US$)<br />
|- <br />
| [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en019469&part=SW007002 MPLAB<sup>®</sup> IDE]<br />
| Assembler Only<br />
| Windows<br />
| Free<br />
|-<br />
| [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en010065&part=SW006012 MPLAB<sup>®</sup> C30]<br />
| Assembler and C-Compiler<br />
| Windows<br />
| $895.00 (Free student version<sup>1</sup>)<br />
|-<br />
| [http://linux.softpedia.com/get/Science-and-Engineering/Electronic-Design-Automation-EDA-/Piklab-8099.shtml Piklab 0.12.0]<br />
| Assembler and C-Compiler<br />
| Linux<br />
| Free<sup>2</sup><br />
|}<br />
# Full-featured for the first 60 days. After 60 days, some code optimization functions are disabled. The compiler will continue to function after 60 days, but code size may increase.<br />
# The current version supports external programmer ICD 2, but not yet tested.<br />
<br />
===RTSP: COM Port (Bootloader)===<br />
*RTSP works in normal voltage (MCLR# no need to raise to V<sub>IHH</sub>).<br />
*No literature has mentioned the incorporation of Programming Executive (PE). Presumably, since Enhanced ICSP needs to set MCLR# to V<sub>IHH</sub>, RTSP cannot use PE.<br />
*Refer to [http://www.opencircuits.com/DsPIC30F_5011_Development_Board#Bootloader_Development bootloader section].<br />
<br />
<br />
==IC Requirements==<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 3.1 IC Requirements<br />
! Part No. !! Description <br />
! Min Temp !! Max Temp !! Min Volt !! Max Volt !! Typ Cur !! Max Cur<br />
|-valign="top"<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/70116F.pdf dsPIC30F5011-30I/PT] || uP <br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 2.5V <sup>[1]</sup>|| 5.5V<br />
| 145mA || 217mA<br />
|-<br />
| [http://datasheets.maxim-ic.com/en/ds/MAX3222-MAX3241.pdf MAX3232ESE] || RS232 driver<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 3.0V || 5.5V<br />
| 0.3mA || 1.0mA<br />
|-<br />
| [http://www.national.com/ds.cgi/DS/DS3695.pdf DS3695N] || RS485 driver<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 4.75V || 5.25V<br />
| 42mA || 60mA<br />
|-<br />
| [http://focus.ti.com/lit/ds/symlink/dac6574.pdf DAC6574IDGS] || 10-bit Quad-DAC I<sup>2</sup>C<br />
| -40<sup>o</sup>C || 105<sup>o</sup>C<br />
| 2.7V || 5.5V<br />
| 0.6mA || 0.9mA<br />
|-<br />
| [http://www.semiconductors.philips.com/acrobat/datasheets/74HC_HCT14_3.pdf 74HC14D] || Quad-Schmitt Trigger<br />
| -40<sup>o</sup>C || 125<sup>o</sup>C<br />
| 2.0V || 6.0V<br />
| || 0.02mA<br />
|-<br />
| '''Overall''' || <br />
| '''-40<sup>o</sup>C''' || '''85<sup>o</sup>C'''<br />
| '''4.75V''' || '''5.25V'''<br />
| || '''<300mA <sup>[2]</sup>'''<br />
|-<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/70165E.pdf dsPIC33FJ128GP306-I/PT] || uP <br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 3.0V <sup>[1]</sup>|| 3.6V<br />
| 74mA || 250mA<br />
|-<br />
| [http://www.analog.com/UploadedFiles/Data_Sheets/ADM3485E.pdf ADM3485EARZ] || RS485 driver<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 3.0V || 3.6V<br />
| 1.1mA || 2.2mA<br />
|-<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/21203N.pdf 24LC256-I/SN] || 256kBits I2C EEPROM<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 2.5V || 5.5V<br />
| 400uA || 3mA<br />
|-<br />
| [http://www.national.com/ds.cgi/LM/LM3940.pdf LM3940IMP-3.3] || 5V-3.3V Regulator<br />
| -40<sup>o</sup>C || 125<sup>o</sup>C<br />
| 5.0V || 7.5V<br />
| 10mA || 250mA<br />
|-<br />
|}<br />
#Minimum voltage measured is 3.3V (with 2 LEDs blinking) running at 30MHz.<br />
#Measured current at 5V is 180mA (with 2 LEDs blinking only)<br />
<br />
<br />
==Development Environment==<br />
<br />
===Windows===<br />
<br />
[[Image:PIC_setup_win.JPG]]<br />
<br />
*C-Compiler, Assembler and Linker are under GNU license.<br />
**MPLAB C30 C Compiler (*.c -> *.s)<br />
**MPLAB ASM30 Assembler (*.s -> *.o)<br />
**MPLAB LINK30 Linker (*.o -> *.bin)<br />
<br />
*PA optimizer, simulator, runtime libraries, header files, include files, and linker scripts are not covered by GNU. Reference is [http://direct.forum.microchip.com/tm.aspx?m=107208 here].<br />
<br />
*Microchip has integrated ASM30, LINK30, assembly header files, linker scripts in MPLAB IDE, which is free for download.<br />
*MPLAB C30 costs US$895. A 60-day free student version is also available. After 60-days, the optimizer is automatically disabled, while other tools can still function properly. Refer to Table 2.4.<br />
<br />
*C-libraries contained in C30 includes (Refer to [http://ww1.microchip.com/downloads/en/DeviceDoc/16bit_Language_Tool_Libraries_51456c.pdf 16-Bit Language Tools Libraries] from Microchip).<br />
<br />
<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 4.1 C Libraries in MPLAB C30<br />
! Library !! Directory <br>(\\Microchip\MPLAB C30) !! Major functions<br />
|-valign="top"<br />
| DSP Library <br>(e.g. libdsp-coff.a)<br />
| \lib <br> \src\dsp <br> \support\h<br />
| Vector, Matrix, Filter, etc.<br />
|-valign="top"<br />
| 16-Bit Peripheral Libraries <br>(e.g. libp30F5011-coff.a)<br />
| \lib <br> \src\peripheral <br> \support\h<br />
| ADC12, IOPort, UART, I<sup>2</sup>C, etc.<br />
|-valign="top"<br />
| Standard C Libraries <br>(e.g. libc-coff.a, libm-coff.a, libpic-coff.a)<br />
| \lib <br> \src\libm <br> \include<br />
| stdio.h, time.h, float.h, math.h, <br />
|-valign="top"<br />
| MPLAB C30 Built-in Functions<br />
| none<br />
| _buildin_addab, _buildin_add, _buildinmpy, etc<br />
|-<br />
|}<br />
<br />
===Linux===<br />
<br />
[[Image:PIC_setup_linux.JPG]]<br />
<br />
*C Compiler, Assembler and Linker are under GNU license.<br />
**The code can be downloaded from Microchip at [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en023073 here].<br />
**Current MPLAB ASM30 Assembler: v2.04<br />
**Current MPLAB C30 Compiler: v2.04<br />
<br />
*[http://gcc.gnu.org/ml/gcc/2005-02/msg01144.html John Steele Scott] has made templates that can be readily used by Debian-based systems. <br />
*For v1.32, the necessary conversion to *.deb has been done already at [http://noel.feld.cvut.cz/dspic/ here].<br />
**Download '''pic30-1.32-debian.tar.bz2''' for Template v1.32.<br />
**Download '''pic30-binutils_1.32-1_i386.deb''' for the assember.<br />
**Download '''pic30-gcc_1.32-1_i386.deb''' for the compiler.<br />
*For v2.00<br />
**goto http://www.baycom.org/~tom/dspic/<br />
**download pic30-gcc-2.00-1.i386.rpm and pic30-binutils-2.00-1.i386.rpm<br />
**convert to deb files<br />
**install these two deb files<br />
*For v3.01, convert the Toolchain following instructions at [http://www.nabble.com/Debian-templates-for-dsPIC-build-toolchain-3.01-tf4308624.html here]<br />
**pre-install these packages: dpkg-dev, debhelper, bison, flex, sysutils, gcc-3.3, fakeroot<br />
**pack pic30-binutils into deb file<br />
**install pic30-binutils<br />
**pack pic30-gcc-3.01 into deb file<br />
**install pic30-gcc-3.01<br />
**pack pic30-support into deb file<br />
**install pic30-support<br />
*'''Important Note''': Only the compiler is free. The header files and library are owned by Microchip. <br />
**Thomas Sailer suggested to download the Student version of C30 compiler and then build the libraries without source code. A package template for Fedora system is available [http://www.baycom.org/~tom/dspic/ here].<br />
**Instructions for filling the upstream direction is available [http://forum.microchip.com/printable.aspx?m=139360 here].<br />
**Alteratively, [https://gna.org/projects/pic30-libc/ Stephan Walter] has started a project to develop C Runtime Library for dsPIC. <br />
***Current libraries in version 0.1.1 include: assert.h, cdefs.h, ctype.h, errno.h, inttypes.h, stdint.h, stdio.h, stdlib.h, string.h<br />
<br />
*Burning Program Codes to Target Board<br />
#Use 'dspicprg and dspicdmp' utilities developed by [http://homerreid.ath.cx/misc/dspicprg/ Homer Reid] to burn hex code (*.hex) to devices. See Reference [http://forum.microchip.com/tm.aspx?m=94243 here]. Through serial port only?<br />
#Use [http://piklab.sourceforge.net/ Piklab IDE]. Details on file format not known.<br />
#Use [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en019469&part=SW007002 MPLAB IDE] to burn hex code (*.hex) to devices.<br />
<br />
===Code Optimization===<br />
*Below is a comparsion between different optimization levels for the project including drivers for 2 projects.<br />
<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 4.2 Comparison between differnt optimization levels<br />
! Optimization !! Description !! Project 1<br>Code Size<br>(byte) !! Project 1<br>Data Usage<br>(byte) !! Project 2<br>Code Size<br>(byte) !! Project 2<br>Data Usage<br>(byte)<br />
|-valign="top"<br />
| O0 <br />
| No optimization<br>Fastest Compilation<br />
| 6222 (9%) || 178 (4%) || 26,037 (38%) || 710 (17%)<br />
|-valign="top"<br />
| O1 <br />
| Optimize<br> Tries to reduce code size and execution time.<br />
| 4473 (6%) || 178 (4%) || 22,290 (32%) || 710 (17%)<br />
|-valign="top"<br />
| O2 <br />
| Optimize even more<br> Performs nearly all supported optimizations <br>that do not involve a space-speed trade-off. <br>Increases both compilation time and the <br>performance of the generated code.<br />
| 4422 (6%) || 178 (4%) || 21,993 (32%) || 710 (17%)<br />
|-valign="top"<br />
| O3 <br />
| Optimize yet more. <br>O3 turns on all optimizations specified by O2 <br>and also turns on the inline-functions option.<br />
| 4485 (6%) || 178 (4%) || 22,176 (32%) || 710 (17%)<br />
|-valign="top"<br />
| Os <br />
| Optimize for size. <br>Os enables all O2 optimizations that do not <br>typically increase code size. It also performs <br>further optimizations designed to reduce code <br>size.<br />
| 4356 (6%) || 178 (4%) || 21,885 (32%) || 710 (17%)<br />
|-<br />
|}<br />
<br />
<br />
==Software Architecture==<br />
+--------+--------+--------+--------+--------+<br />
Application | Task 1 | Task 2 | Task 3 | Task 4 | Task 5 |<br />
+--------+--------+--------+--------+--------+<br />
| POSIX API |<br />
+-------------------+------------------------+<br />
OS | Coroutine | FreeRTOS Scheduler |<br />
+-------------------+------------------------+<br />
| Drivers |<br />
+------+-----+-----+--------+-------+--------+<br />
Hardware | UART | ADC | DAC | EEPROM | PWM | TIMERS | <br />
+------+-----+-----+--------+-------+--------+<br />
*Currently, operating system is based on [http://www.freertos.org/ FreeRTOS] incorporating coroutine developed by [http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html Simon Tatham]<br />
*Software Drivers are to be developed to allow users at Application Level to use the hardware (e.g. ADC, DAC, UART, EEPROM etc) through the OS.<br />
*The interface between the drivers and the OS is based on [http://www.die.net/doc/linux/man/man2/ POSIX standard] (e.g. open(), write(), read(), ioctl(), usleep() etc).<br />
*The most up-to-date development can be found at repository [http://chungyan5.no-ip.org/vc/?root=freertos_posix freertos_posix]<br />
<br />
<br />
==Programming Tips==<br />
<br />
===Memory Map for 5011===<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 6.1 Memory Location<br />
! Type !! Start Address !! End Address !! Size<br />
|-valign="top"<br />
| Flash || 0x000000 ||0x00AFFF || 44K<sup>[1]</sup><br />
|-valign="top"<br />
| +--Flash: Reset Vector || 0x000000 ||0x000003 || 4<br />
|-valign="top"<br />
| +--Flash: Interrupt Vector Table || 0x000004 ||0x00007F || 124<br />
|-valign="top"<br />
| +--Flash: Alternate Vector Table || 0x000084 ||0x0000FF || 124<br />
|-valign="top"<br />
| +--Flash: User Program || 0x000100 ||0x00AFFF || 43.7K<br />
|-valign="top"<br />
| EEPROM || 0x7FFC00 || 0x7FFFFF || 1K<sup>[2]</sup><br />
|-valign="top"<br />
| Programming Executive || 0x800000 || 0x8005BF || 1472<br />
|-valign="top"<br />
| Unit ID || 0x8005C0 || 0x8005FF || 64<br />
|-valign="top"<br />
| Config Registers || 0xF80000 || 0xF8000F || 16<br />
|-valign="top"<br />
| Device ID || 0xFF0000 || 0xFF0003 || 4<br />
|-<br />
|}<br />
[1] Each address is 16-bit wide. Every two addresses correspond to a 24-bit instruction. Each even address contains 2 valid bytes; each odd address contains 1 valid byte plus 1 phathom byte.<br><br />
[2] Each address is 8-bit wide.<br />
<br />
===Data Location===<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 6.2 Data Location<br />
! Type !! Description !! Example<br />
|-valign="top"<br />
| _XBSS(N) <sup>[1]</sup><br />
| RAM Data in X-memory, aligned at N, no initilization<br />
| int _XBSS(32) xbuf[16];<br />
|-valign="top"<br />
| _XDATA(N) <sup>[1]</sup><br />
| RAM Data in X-memory, aligned at N, with initilization<br />
| int _XDATA(32) xbuf[] = {1, 2, 3, 4, 5};<br />
|-valign="top"<br />
| _YBSS(N) <sup>[1]</sup><br />
| RAM Data in Y-memory, aligned at N, no initilization<br />
| int _YBSS(32) ybuf[16];<br />
|-valign="top"<br />
| _YDATA(N) <sup>[1]</sup><br />
| RAM Data in Y-memory, aligned at N, with initilization<br />
| int _YDATA(32) ybuf[16] = {1, 2, 3, 4, 5};<br />
|-valign="top"<br />
| __attribute__((space(const)))<br />
| Flash ROM data, constant, accessed by normal C<br>statements, but 32K max.<br />
| int i __attribute__((space(const))) = 10;<br />
|-valign="top"<br />
| __attribute__((space(prog)))<br />
| Flash ROM data, read/write by program space visibility<br>window (psv)<br />
| int i __attribute__((space(prog)));<br />
|-valign="top"<br />
| __attribute__((space(auto_psv)))<br />
| Flash ROM data, read by normal C statements, write<br>by accessing psv<br />
| int i __attribute__((space(auto_psv)));<br />
|-valign="top"<br />
| __attribute__((space(psv)))<br />
| Flash ROM data, read/write by (psv)<br />
| int i __attribute__((space(psv)));<br />
|-valign="top"<br />
| _EEDATA(N) <sup>[1]</sup><br />
| ROM Data in EEPROM, aligned at N, read/write with psv<br />
| int _EEDATA(2) table[]={0, 1, 2, 3, 5, 8};<br />
|-valign="top"<br />
| _PERSISTENT<br />
| RAM Data, data remain after reset<br />
| int _PERSISTENT var1, var2;<br />
|-valign="top"<br />
| _NEAR<br />
| RAM Data at near section<br />
| int _NEAR var1, var2;<br />
|-valign="top"<br />
| _ISR<br />
| Interrupt service rountine<br />
| void _ISR _INT0Interrupt(void);<br />
|-valign="top"<br />
| _ISRFAST<br />
| Fast interrupt service rountine<br />
| void _ISRFAST _T0Interrupt(void);<br />
|-<br />
|}<br />
#N must be a power of two, with a minimum value of 2.<br />
<br />
===Configuration Bits===<br />
----<br />
*System clock source can be provided by:<br />
#Primary oscillator (OSC1, OSC2)<br />
#Secondary oscillator (SOSCO and SOSCI) with 32kHz crystal<br />
#Internal Fast RC (FRC) oscillator at 7.37MHz (7372800Hz)<br />
#Low-Power RC (LPRC) oscillator (Watchdog Timer) at 512 kHz.<br />
*These clock sources can be incorporated with interal Phase-locked-loop (PLL) x4, x8 or x16 to yield the osciallator frequrence F<sub>OSC</sub><br />
*The system clock is divided by 4 to yield the internal instruction cycle clock, F<sub>CY</sub>=F<sub>OSC</sub>/4<br />
*FRC with PLLx16 is used to achieve F<sub>CY</sub>=29.49MHz (29491200Hz or 30MIPS)<br />
<br />
//The code (MACRO) below is to be placed at the top of program (before main)<br />
_FOSC(CSW_FSCM_OFF & FRC_PLL16);<br />
_FWDT(WDT_OFF); //Turn off Watchdog Timer<br />
_FBORPOR(PBOR_ON & BORV_27 & MCLR_DIS & PWRT_16);<br />
_FGS(CODE_PROT_OFF); //Disable Code Protection<br />
<br />
===Timer===<br />
<br />
----<br />
*Each timer is 16-bit (i.e. counting from 0 to 65535).<br />
*Timer 2 and 3 can be incorporated together to form a 32-bit timer.<br />
*Prescale is the ratio between timer counts and system clock counts. Prescales of 1:1, 1:8, 1:64 and 1:256 are available.<br />
*Timers may be used to implement free time clock or mesaure time.<br />
<br />
====Free Time Clock====<br />
*Let required time for ticking be PERIOD.<br />
*Number of instruction cycles during PERIOD = PERIOD*F<sub>CY</sub> cycles<br />
*Using a prescale of 1:x, the timer period count register = # of cycles/x<br />
*e.g. PERIOD = 10ms; # of cycles = 10ms*30MHz = 300000 cylces; Using 1:64 Prescale, register setting = 300000/64 = 4688<br />
void time_init(void){<br />
TMR1 = 0; // Clear register<br />
PR1 = 4688; // Set period<br />
//============================================================<br />
_T1IF = 0; // Clear interrupt flag<br />
_T1IE = 1; // Enable interrupts<br />
//============================================================<br />
T1CONbits.TCS = 0; // Use internal clock source<br />
T1CONbits.TCKPS = 2; // Prescale Select 1:64<br />
T1CONbits.TON = 1; // Start the timer <br />
}<br />
//********************************************************************<br />
void _ISRFAST _T1Interrupt(void){<br />
_T1IF = 0; // Clear interrupt flag<br />
//Place user code here<br />
}<br />
<br />
====Time Measurement====<br />
*To measure the time taken for action(), use the code below:<br />
unsigned int measure_time(void){ <br />
PR3 = 0xFFFF; // Set counter to maximum<br />
_T3IF = 0; // Clear interrupt flag<br />
_T3IE = 0; // Disable interrupt<br />
T3CONbits.TON = 1; // Start the timer, TMR3 count up<br />
TMR3 = 0; //Clear TMR3 to start count up<br />
//====================================================<br />
//Add code here to wait for something to happen<br />
action();<br />
//====================================================<br />
T3CONbits.TON = 0; //Stop the timer<br />
//====================================================<br />
return (unsigned int) TMR3/FCY; //TMR/FCY yields the actual time<br />
}<br />
<br />
===Interrupt===<br />
<br />
----<br />
*Registers are involved in Interrupts includes: <br />
#Interrupt Flag Status (IFS0-IFS2) registers<br />
#Interrupt Enable Control (IEC0-IEC2) registers<br />
#Interrupt Priority Control (IPC0-IPC10) registers<br />
#Interrupt Priority Level (IPL) register<br />
#Global Interrupt Control (INTCON1, INTCON2) registers<br />
#Interrupt vector (INTTREG) register<br />
*User may assign priority level 0-7 to a specific interrupt using IPC. Setting priority to 0 disable a specific interrupt. Level 7 interrupt has the highest priority.<br />
*Current priority level is stored in bit<7:5> of Status Register (SR). Setting Interrupt Priority Level (IPL) to 7 disables all interrupts (except traps). <br />
*sti() and cli() can be defined to enable and disable global interrupts for time critical functions:<br />
#define IPL ( 0x00e0 )<br />
#define cli() SR |= IPL //Set IPL to 7<br />
#define sti() SR &= ~IPL //Set IPL to 0<br />
//============================================================<br />
char adc_ioctl(unsigned char request, unsigned char* argp){<br />
//...<br />
cli(); //Disable global interrupt<br />
for(;ch<=argp[0];ch++)<br />
adc_add_ch(argp[ch]); //Add adc channels<br />
sti(); //Enable global interrupt<br />
//...<br />
return 0;<br />
}<br />
*dsPic30F has an [http://ww1.microchip.com/downloads/en/DeviceDoc/80223D.pdf errate note] on the Interrupt Controller. When Nested Interrupt is turned on (NSTDIS=0 by default), a high priority interrupt negating a low priority interrupt may result in an Address Error.<br />
*To work around the problem, it is suggested by Microchip to use the following MACRO to protect:<br />
# the clearing of Interrput Flag<br />
# the disabling of Interrupt Enable<br />
# the lowering of Interrupt Priority <br />
# the modification of IPL in Status Register to 1-6<br />
#define DISI_PROTECT(X) { \<br />
__asm__ volatile ("DISI #0x1FFF");\<br />
X; \<br />
DISICNT = 0; \<br />
}<br />
*For example,<br />
void _ISR _T1Interrupt( void )<br />
{<br />
DISI_PROTECT(IFS0bits.T1IF = 0);<br />
//do something here...<br />
}<br />
<br />
===UART===<br />
<br />
----<br />
*5011 provides two UART channels UxART, for x=1, 2.<br />
*UxMODE, UxSTA, UxBRG are registers used to set the mode, indicate the status, and set the baud rate respectively.<br />
*For UART communications compatiable with RS232 standard, an external driver (e.g. MAX3232ESE) is needed.<br />
*For UART communications compatiable with RS485 standard, an external driver (e.g. DS3695N) is needed.<br />
====Auto baud rate detection====<br />
*The method is provided by [http://www.opencircuits.com/DsPIC30F_5011_Development_Board ingenia bootloader].<br />
*The PC sends a ASCII character 'U' (0x55) to the target board.<br />
*On the first rising edge of the start bit, the target board starts the timer.<br />
*At the fifth rising edge, the timer is stopped, let the count number be ''t_count''. <br />
**The measured period corresponds to 8 bits transmitted at a baud rate ''uxbrg''.<br />
_ _ _ _ _ _<br />
_|S|_|1|_|1|_|1|_|1|_|S|_ (S = Start Bit)<br />
<---------------><br />
Measured Time<br />
*The relationship between ''uxbrg'' and ''TMR'' is<br />
Measured Time (in seconds) = t_count/F<sub>cy</sub><br />
uxbrg = 1/(Measured Time/8)<br />
= 8*F<sub>cy</sub>/t_count<br />
*Since UxBRG is computed by:<br />
UxBRG = (F<sub>cy</sub>/(16*Baudrate)) -1<br />
= (F<sub>cy</sub>/(16*8*F<sub>cy</sub>/t_count)) -1<br />
= t_count/128 -1<br />
*The following is the code for auto baud rate detection for U2ART:<br />
unsigned int uart2_autobaud(void){<br />
U2MODEbits.ABAUD = 1; //Enable Autobaud detect from U2RX (from IC2 if 0)<br />
U2MODEbits.UARTEN = 1; //U2ART enable<br />
//Timer 3 Config==========================================================<br />
PR3 = 0xFFFF; // Set counter to maximum<br />
_T3IF = 0; // Clear interrupt flag<br />
_T3IE = 0; // Disable interrupt<br />
T3CONbits.TON = 1; // Start the timer, TMR3 count up<br />
//Input Capture Config====================================================<br />
IC2CONbits.ICM = 3; //Detect rising <br />
_IC2IF = 0; //Clear interrupt flag<br />
_IC2IE = 0; //Disable interrupt<br />
//Start Auto baud detection===============================================<br />
unsigned int i=0;<br />
cli(); //Disable Global Interrupt<br />
while(!_IC2IF); //1st rising edge detected<br />
TMR3 = 0; //Clear TMR3 to start count up<br />
_IC2IF = 0; //Clear interrupt flag<br />
while(!_IC2IF); //2nd rising edge detected<br />
_IC2IF = 0; //Clear interrupt flag<br />
while(!_IC2IF); //3rd rising edge detected<br />
_IC2IF = 0; //Clear interrupt flag<br />
while(!_IC2IF); //4th rising edge detected<br />
_IC2IF = 0; //Clear interrupt flag<br />
while(!_IC2IF); //5th rising edge detected<br />
_IC2IF = 0; //Clear interrupt flag<br />
T3CONbits.TON = 0; //Stop the timer<br />
sti(); //Enable Global Interrupt<br />
//Compute value for BRG register==========================================<br />
unsigned int time;<br />
time = ((TMR3+0x40)>>7)-1; //+0x40 for rounding<br />
//========================================================================<br />
return time;<br />
}<br />
*For 30MIP, tested speeds of transmission include 9600bps, 19200bps, 28800bps, 38400bps and 57600bps.<br />
====open()====<br />
*The following structures and variables are used as circular buffers for transmit and receive.<br />
struct UART_Rx{<br />
unsigned char wr;<br />
unsigned char rd;<br />
};<br />
struct UART_Tx{<br />
unsigned char wr; <br />
unsigned char rd;<br />
unsigned char tx_complete_flag;<br />
};<br />
struct UART_Rx uart_rx;<br />
struct UART_Tx uart_tx;<br />
unsigned char uart_rx_buf[MAX_UART_RX_BUF];<br />
unsigned char uart_tx_buf[MAX_UART_TX_BUF];<br />
<br />
char uart_open()<br />
{<br />
uart_rx.wr = 0;<br />
uart_rx.rd = 0;<br />
uart_tx.wr = 0;<br />
uart_tx.rd = 0;<br />
uart_tx.tx_complete_flag = 1;<br />
uart2_init();<br />
return 0;<br />
}<br />
<br />
void uart2_init(void){<br />
unsigned int u2brg = 97; <br />
#if(AUTO_BAUD_DECT>0)<br />
u2brg = uart2_autobaud();<br />
#endif<br />
U2BRG = u2brg; <br />
//=================================================================<br />
// Disable U2ART<br />
U2MODEbits.UARTEN = 0; //Disable U2ART module<br />
//=================================================================<br />
// Configure Interrupt Priority<br />
_U2RXIF = 0; //Clear Rx interrupt flags<br />
_U2TXIF = 0; //Clear Tx interrupt flags<br />
_U2RXIE = 1; //Receive interrupt: 0 disable, 1 enable <br />
_U2TXIE = 1; //Transmit interrupt: 0 disable, 1 enable<br />
//=================================================================<br />
// Configure Mode<br />
// +--Default: 8N1, no loopback, no wake in sleep mode, continue in idle mode<br />
// +--Diable autobaud detect<br />
// +--Enable U2ART module<br />
U2MODEbits.ABAUD = 0; //Disable Autobaud detect from U2RX <br />
U2MODEbits.UARTEN = 1; //U2ART enable<br />
//=================================================================<br />
// Configure Status<br />
// +--Default: TxInt when a char is transmitted, no break char<br />
// +--Default: RxInt when a char is received, no address detect, clear overflow<br />
// +--Enable Transmit<br />
U2STAbits.UTXEN = 1; //Tx enable<br />
}<br />
<br />
====write()====<br />
*This function writes a series of bytes to the circular buffer and start transmission.<br />
int uart_write(unsigned char *buf, int count)<br />
{<br />
//If transimt has not completed, return busy<br />
if(uart_tx.tx_complete_flag == 0){<br />
return -1; <br />
}<br />
else{<br />
uart_tx.tx_complete_flag = 0;<br />
}<br />
int next_data_pos;<br />
int byte = 0;<br />
for (; byte<count; byte++) {<br />
next_data_pos = pre_wr_cir254buf( (unsigned char)uart_tx.wr, <br />
(unsigned char)uart_tx.rd, <br />
MAX_UART_TX_BUF); <br />
if (next_data_pos!=255) {<br />
//Valid data is available<br />
uart_tx_buf[uart_tx.wr] = (unsigned char) buf[byte]; //copy the char to tx_buf<br />
uart_tx.wr = next_data_pos; //increment the ptr<br />
} else break;<br />
}<br />
//Raise Interrupt flag to initiate transmission<br />
_U2TXIF = 1; //Start interrupt<br />
return byte; <br />
}<br />
*The interrupt routine reads from the circular buffer and send the data. The uart is opened such that the module will generate an TX Interrupt when it a byte is sent.<br />
void _ISR _U2TXInterrupt(void){<br />
DISI_PROTECT(_U2TXIF = 0); //Clear Interrupt Flag<br />
unsigned char next_data_pos;<br />
next_data_pos = pre_rd_cir254buf( (unsigned char)uart_tx.wr,<br />
(unsigned char)uart_tx.rd, <br />
MAX_UART_TX_BUF);<br />
if (next_data_pos!= 255) {<br />
//Valid Data is available to transmit<br />
U2TXREG = (uart_tx_buf[(unsigned char)uart_tx.rd] & 0xFF); //send next byte...<br />
uart_tx.rd = (unsigned char) next_data_pos; //update rd pointer<br />
} else {<br />
//Transimission has completed<br />
uart_tx.tx_complete_flag = 1; // change to empty of tx<br />
}<br />
}<br />
<br />
====read()====<br />
*The interrupt routine writes to the circular buffer when space is available.<br />
void _ISR _U2RXInterrupt(void){<br />
unsigned char next_data_pos;<br />
if ( U2STAbits.URXDA ){<br />
next_data_pos = pre_wr_cir254buf( uart_rx.wr, uart_rx.rd, MAX_UART_RX_BUF);<br />
if (next_data_pos!=255) {<br />
//If buffer is not full<br />
uart_rx_buf[uart_rx.wr] = (unsigned char) U2RXREG; //Read the data from buffer<br />
uart_rx.wr = next_data_pos;<br />
} <br />
else{<br />
//When buffer is full, still remove data from register, butthe incoming data is lost<br />
next_data_pos = (unsigned char) U2RXREG; //Read the data from buffer<br />
} <br />
}<br />
DISI_PROTECT(_U2RXIF = 0); //Clear the flag<br />
}<br />
*This function reads one byte from the circular buffer.<br />
int uart_read(unsigned char *buf)<br />
{<br />
int next_data_pos;<br />
next_data_pos = pre_rd_cir254buf( uart_rx.wr, uart_rx.rd, MAX_UART_RX_BUF);<br />
//Copy 1 byte when data is available<br />
if (next_data_pos!=255) <br />
{<br />
*buf = uart_rx_buf[uart_rx.rd]; //copy the stored data to buf<br />
uart_rx.rd = next_data_pos; //update the ptr<br />
return 1;<br />
}<br />
//No data can be copied<br />
else<br />
{<br />
return 0;<br />
} <br />
}<br />
<br />
===I<sup>2</sup>C===<br />
<br />
----<br />
*Two lines are devoted for the serial communication. SCL for clock, SDA for data.<br />
*Standard communication speed includes<br />
#Standard speed mode: 100kHz<br />
#Fast speed mode: 400kHz<br />
#High speed mode: 3.4MHz<br />
*dsPIC30f5011 supports standard and fast speed modes. The maximum speed attainable is 1MHz.<br />
*Pull-up resistors are required for both SCL and SDA. Minimum pull-up resistance is given by:<br />
Pull-up resistor (min) = (V<sub>dd</sub>-0.4)/0.003 ...... [See section 21.8 in Family reference manual]<br />
*2.2Kohm is typical for standard speed mode.<br />
*After initiating a start/stop/restart bit, add a small delay (e.g. no operation) before polling the corresponding control bit (hardware controlled).<br />
*After sending a byte and receiving an acknowledgement from the slave device, ensure to change to idle state.<br />
<br />
====open()====<br />
*The following structure is used to record whether special bits are needed to be sent.<br />
typedef union{<br />
unsigned char val;<br />
struct{<br />
unsigned START:1; //start<br />
unsigned RESTART:1; //restart<br />
unsigned STOP:1; //stop<br />
unsigned NACK:1; //not acknowledgment<br />
unsigned :1;<br />
unsigned :1;<br />
unsigned :1;<br />
unsigned :1; <br />
}bits;<br />
} I2C_STATUS;<br />
static I2C_STATUS i2c_status; <br />
<br />
*Initializing I<sup>2</sup>C with default speed I2C_BRG without interrupts.<br />
void i2c_open(void)<br />
{<br />
//Open i2c if not already opened<br />
if(I2CCONbits.I2CEN == 0)<br />
{<br />
_SI2CIF = 0; //Clear Slave interrupt<br />
_MI2CIF = 0; //Clear Master interrupt<br />
_SI2CIE = 0; //Disable Slave interrupt<br />
_MI2CIE = 0; //Disable Master interrupt<br />
I2CBRG = I2C_BRG;<br />
I2CCONbits.I2CEN = 1; //Enable I2C module <br />
i2cIdle(); //I2C bus at idle state, awaiting transimission<br />
i2c_status.val = 0; //clear status flags<br />
}<br />
}<br />
<br />
====ioctl()====<br />
*Use this function before read/write to append special bits before or after the data byte.<br />
char i2c_ioctl(unsigned char request, unsigned char* argp)<br />
{<br />
switch(request){<br />
case I2C_SET_STATUS:<br />
i2c_status.val = *argp;<br />
break;<br />
default:<br />
return -1; //request code not recognised <br />
}<br />
return 0;<br />
}<br />
<br />
====write()====<br />
*This function sends an 8-bit data using the I2C protocol.<br />
Mst/Slv _______ M ____M___ S M ________ <br />
SDA (Data) |S| data |A|S|<br />
|T| |C|T|<br />
|A|XXXXXXXX|K|P|<br />
*Use ioctl() to select whether a start/restart/stop bit is required.<br />
*If slave does not respond after ACK_TIMEOUT, the transmission is considered unsucessful.<br />
int i2c_write(unsigned char *buf)<br />
{<br />
unsigned int count = 0;<br />
if(i2c_status.bits.START)<br />
{<br />
I2CCONbits.SEN = 1; <br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.SEN); //Wait till Start sequence is completed<br />
}<br />
else if(i2c_status.bits.RESTART)<br />
{<br />
I2CCONbits.RSEN = 1; <br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.RSEN); //Wait till Start sequence is completed<br />
}<br />
I2CTRN = *buf; //Transmit register<br />
while(I2CSTATbits.TBF); //Wait for transmit buffer to empty<br />
while(I2CSTATbits.ACKSTAT){<br />
if(++count > ACK_TIMEOUT){<br />
//Slave did not acknowledge, byte did not transmit sucessfully, <br />
//send stop bit to reset i2c<br />
I2CCONbits.PEN = 1;<br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.PEN); //Wait till stop sequence is completed<br />
i2cIdle();<br />
return 0;<br />
}<br />
}<br />
i2cIdle();<br />
if(i2c_status.bits.STOP)<br />
{<br />
I2CCONbits.PEN = 1;<br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.PEN); //Wait till stop sequence is completed<br />
i2cIdle();<br />
}<br />
i2c_status.val = 0; //Clear status<br />
return 1;<br />
}<br />
<br />
====read()====<br />
*This function reads 1 byte from slave using the I2C protocol.<br />
Mst/Slv ____ ___S____ M M _____ <br />
SDA (Data) | data |A|S|<br />
| |C|T|<br />
|XXXXXXXX|K|P|<br />
*Use ioctl() to select whether an ACK/NACK and/or STOP bit is needed to be sent.<br />
int i2c_read(unsigned char *buf)<br />
{<br />
I2CCONbits.RCEN = 1; //Enable Receive<br />
while(I2CCONbits.RCEN);<br />
I2CSTATbits.I2COV = 0; //Clear receive overflow<br />
*buf = (unsigned char) I2CRCV; //Access the receive buffer<br />
I2CCONbits.ACKDT = (i2c_status.bits.NACK)? 1 : 0;<br />
I2CCONbits.ACKEN = 1; //Send Acknowledgement/Not Acknowledgement<br />
i2cIdle(); //I2C bus at idle state, awaiting transimission<br />
if(i2c_status.bits.STOP)<br />
{<br />
I2CCONbits.PEN = 1;<br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.PEN); //Wait till stop sequence is completed<br />
i2cIdle();<br />
}<br />
i2c_status.val = 0; //Clear status<br />
return 1;<br />
}<br />
<br />
====Example====<br />
Mst/Slv _______ M ___M___ M S ____M___ S M ___M___ M S ___S____ M ___S____ M M _____ <br />
SDA (Data) |S| | |A| |A|R| | |A| |A| |N|S|<br />
|T|address|W|C|channelA|C|E|address|R|C| Data H |C| Data L |A|T|<br />
|A|1001111|0|K|00010010|K|S|1001111|1|K|10101010|K|10XXXXXX|K|P|<br />
<br />
/*<br />
* Send start bit, slave address (Write Mode)<br />
*/ <br />
status = I2C_START;<br />
i2c_ioctl(I2C_SET_STATUS, &status);<br />
data = (unsigned char) I2C_SLAVE_ADDR;<br />
i2c_write(&data);<br />
/*<br />
* Send control byte: Channel select<br />
*/<br />
data = (unsigned char) ctrl_byte;<br />
i2c_write(&data);<br />
/*<br />
* Send restart bit, slave address (Read Mode)<br />
*/<br />
status = I2C_RESTART;<br />
i2c_ioctl(I2C_SET_STATUS, &status);<br />
data = (unsigned char) (I2C_SLAVE_ADDR|0x01);<br />
i2c_write(&data);<br />
/*<br />
* Receive High Byte with Acknowledgment<br />
*/<br />
i2c_read(&data);<br />
usr_data.high = (unsigned char) data;<br />
/*<br />
* Receive Low Byte with Not Acknowledgment and stop bit<br />
*/ <br />
status = I2C_NACK | I2C_STOP;<br />
i2c_ioctl(I2C_SET_STATUS, &status);<br />
i2c_read(&data);<br />
usr_data.low = (unsigned char) data;<br />
<br />
===ADC===<br />
<br />
----<br />
*12-bit ADC: (Max 16 Channels)<br />
*Allow a maximum of 2 sets of analog input multiplexer configurations, MUX A and MUX B (Normally use one only).<br />
*A maximum of 200kps of sampling rate when using auto sampling mode.<br />
====open()====<br />
*The following variables are required.<br />
unsigned int adc_buf[ADC_MAX_CH]; //Store most updated data<br />
volatile unsigned int* ADC16Ptr = &ADCBUF0; //Pointer to ADC register buffer, <br />
unsigned char adc_ch_select = 0; //Pointer to channel to be read from<br />
unsigned char adc_data_ready = 0; //Indicate if RAM data is ready for output<br />
*Configuration is highlighted below.<br />
**Interrupt: The ADC module will be set to interrupt when the specified channels are updated.<br />
**I/O: Set the corresponding TRISBX bits (digit i/o config) to input (i.e. = 1), and set corresponding bits in ADPCFG (analog config) to zero.<br />
**Scanning Mode: Scan mode is used. In this mode, the Sample and Hold (S/H) is switched between the channels specified by ADCSSL (Scan select register).<br />
**Reference Voltage for S/H: Only MUX A is used. By default, the negative reference voltage of the S/H is connected to V<sub>REF-</sub>.<br />
**Settings for ADC Operation: For 200kbps operation, the voltage references for the ADC voltage are connected to V<sub>REF+</sub> and V<sub>REF-</sub>. Scan input is enabled, and the module will generate an interrupt when all selected channels have been scanned.<br />
**Sampling Rate: T<sub>AD</sub> refers to the time unit for the ADC clock. To configure the ADC module at 200kbps, the minimum sampling time of 1T<sub>AD</sub> = 334ns is required. ADCS<5:0> in ADCON3 register is used to set the time, which is given by:<br />
ADCS<5:0> = 2(T<sub>AD</sub>/T<sub>CY</sub>)-1 <br />
= 2(334e-9/33.34e-9)-1 <br />
= 19<br />
<br />
char adc_open(int flags)<br />
{<br />
// Configure interrupt<br />
_ADIF = 0; //clear ADC interrupt flag<br />
_ADIE = 1; //enable adc interrupt<br />
// Configure analog i/o <br />
_TRISB0 = 1;<br />
_TRISB1 = 1; <br />
ADPCFG = 0xFFFC; //Enable AN0 (Vref+) and AN1 (Vref-)<br />
// Configure scan input channels <br />
ADCSSL = 0x0003; //0 => Skip, 1 => Scan<br />
// Configure CH0 Sample and Hold for 200kbps<br />
// +-- Use MUX A only<br />
// +-- Set CH0 S/H -ve to VRef-<br />
ADCHSbits.CH0NA = 0;<br />
// ADCCON3:<br />
// +--Auto Sample Time = 1TAD<br />
// +--A/D Conversion Clock Source = system clock<br />
// +--A/D Conversion Clock Select ADCS<5:0>= 2(TAD/TCY)-1<br />
// 200kbps(Sampling frequency)<br />
ADCON3bits.SAMC = ADC_ACQ_TIME; //1TAD for sampling time<br />
ADCON3bits.ADRC = 0; //Use system clock<br />
ADCON3bits.ADCS = ADC_ADCS; //each conversion requires 14TAD<br />
// ADCCON2:<br />
// +--Default: Use MUX A, No splitting of Buffer<br />
// +--Voltage Reference Configuration Vref+ and Vref-<br />
// +--Scan Input Selections<br />
// +--5 samples between interrupt<br />
ADCON2bits.VCFG = 3; //External Vref+, Vref-<br />
ADCON2bits.CSCNA = 1; //Scan input<br />
ADCON2bits.SMPI = 1; //take 2 samples (one sample per channel) per interrupt<br />
// ADCCON1:<br />
// +--Default: continue in idle mode, integer format<br />
// +--Enable ADC, Conversion Trigger Source Auto, Auto sampling on<br />
ADCON1bits.FORM = 0; //[0:integer]; [2 fractional]; [3 siged fractional]<br />
ADCON1bits.SSRC = 7; //auto covert, using internal clock source<br />
ADCON1bits.ASAM = 1; //auto setting of SAMP bit<br />
ADCON1bits.ADON = 1; //Turn on module<br />
return 0;<br />
}<br />
<br />
====read()====<br />
*16 registers (ADCBUF0 -ADCBUF15) are dedicated to store the ADC data between interrupts. However, the data in ADCBUFx does not necessarily correspond to the data taken for channel x. Since the lowest register will always be filled first, when some of the channels are not scanned (i.e. skipped), care must be taken. The following code checks the ADCSSL register for the current scanning channels and moves the data to the corresponding position in *adc_buf.<br />
void _ISR _ADCInterrupt(void){<br />
unsigned int channel = 0;<br />
unsigned int buffer = 0;<br />
for (; channel<ADC_MAX_CH; channel++)<br />
{<br />
if(select(channel)) //Check if channel has been selected<br />
{<br />
adc_buf[channel] = ADC16Ptr[buffer]; //Copy data to adc_buf<br />
buffer++;<br />
}<br />
}<br />
adc_data_ready = 1;<br />
DISI_PROTECT(_ADIF = 0); //Clear adc interrupt<br />
}<br />
<br />
static unsigned char select(unsigned char ch)<br />
{<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
if(ADCSSL & mask)<br />
return 1;<br />
return 0;<br />
}<br />
*User can read from the buffer at anytime to get the most updated analog values.<br />
int adc_read(unsigned int* buf, int count)<br />
{<br />
if(adc_data_ready == 1)<br />
{<br />
int num_channel = count/2; //number of channels to read<br />
unsigned char channel = adc_ch_select; //index for adc_buf<br />
int i = 0; //index for buf<br />
while(i<num_channel && channel<ADC_MAX_CH)<br />
{ <br />
//Loop only for specified number of channel or all channels <br />
buf[i++] = adc_buf[channel++]; //use data in local buffer<br />
while(select(channel)==0)<br />
{ //increment to next valid channel<br />
channel++; <br />
if(channel >= ADC_MAX_CH) break;<br />
}<br />
}<br />
return 2*i;<br />
}<br />
return -1;<br />
}<br />
<br />
====ioctl()====<br />
*This function is used to add or remove channels from the ADC scanning process.<br />
char adc_ioctl(unsigned char request, unsigned char* argp)<br />
{<br />
switch(request)<br />
{<br />
case ADC_ADD_CH:<br />
//ADD channels to current set==========================<br />
cli(); //Disable global interrupt<br />
if(select(argp[0]) == 0){ //If channel not in scan list<br />
adcAdd(argp[0]); //Add individual channel to scan list<br />
adc_data_ready = 0; //First data not ready yet, until interrupt occurs<br />
}<br />
adc_ch_select = argp[0]; //Select current channel for reading<br />
sti(); //Enable global interrupt<br />
break;<br />
case ADC_RM_CH:<br />
//REMOVE channels from current set==========================<br />
cli(); //Disable global interrupt<br />
if(select(argp[0])){ //If channel in scan list <br />
adcRm(argp[0]); //Remove individual channel<br />
adc_ch_select = 0; //Reset to AN0<br />
}<br />
sti(); //Enable global interrupt<br />
break;<br />
default:<br />
return -1; //request code not recognised <br />
}<br />
return 0;<br />
}<br />
*Channels may be added or removed by changing _TRISBX, ADPCFG, ADCSSL and ADCON2bits.SMPI.<br />
void adc_add_ch(unsigned char ch){<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
TRISB = TRISB | mask;<br />
ADCSSL = ADCSSL | mask; <br />
ADPCFG = ~ADCSSL;<br />
ADCON2bits.SMPI++; //take one more sample per interrupt<br />
}<br />
<br />
void adc_rm_ch(unsigned char ch){<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
ADPCFG = ADPCFG | mask;<br />
ADCSSL = ~ADPCFG;<br />
ADCON2bits.SMPI--; //take one less sample per interrupt<br />
}<br />
<br />
===EEPROM===<br />
<br />
----<br />
*5011 has 1024 bytes of EEPROM, readable and writable under normal voltage (5V).<br />
*To use, declare:<br />
unsigned char _EEDATA(2) eeData[1024]={ 0x00, 0x00, 0x00, 0x00, .... }<br />
unsigned int byte_pointer = 0;<br />
====lseek()====<br />
*This function moves the pointer to the desired position before a reading/writing operation is performed.<br />
int eeprom_lseek(int offset, unsigned char whence){<br />
byte_pointer = offset;<br />
return byte_pointer;<br />
}<br />
====read()====<br />
*This function read ''count'' bytes from the eeprom.<br />
int eeprom_read(unsigned char* buf, int count){<br />
int i=0;<br />
for(; i<count && byte_pointer < 1024; i++){<br />
readEEByte( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + byte_pointer, <br />
&buf[i]);<br />
byte_pointer++; //Update global pointer<br />
}<br />
return i; //read i bytes successful <br />
}<br />
*readEEByte() is implemented in assembly code as follows:<br />
.global _readEEByte<br />
_readEEByte:<br />
push TBLPAG ;w0 = base of eeData<br />
mov w0, TBLPAG ;w1 = offset for eeData in byte<br />
tblrdl.b [w1], [w2] ;w2 = pointer to user buffer<br />
pop TBLPAG<br />
return<br />
<br />
====write()====<br />
*This function write ''count'' bytes to eeprom.<br />
int eeprom_write(unsigned char* buf, int count){<br />
char isOddAddr = byte_pointer%2; //current address is odd<br />
char isOddByte = count%2; //number of bytes to write is odd<br />
//=================================================================<br />
unsigned int word_offset = byte_pointer>>1; //div by 2 and round down<br />
int max_write;<br />
max_write = (isOddAddr == 0 && isOddByte == 0) ? (count>>1) : (count>>1)+1;<br />
//=================================================================<br />
unsigned int word_data; //Store word to be written<br />
int byte_wr = 0; //number of bytes written, i.e buffer pointer<br />
int i = 0;<br />
//=================================================================<br />
for(; i<max_write && word_offset<512; i++, word_offset++){<br />
if(i==0 && isOddAddr){<br />
//First byte not used<br />
//============================================save first byte<br />
readEEByte( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + byte_pointer - 1,<br />
&word_data);<br />
//===========================================================<br />
word_data = ((unsigned int)buf[0] << 8) + (0xFF & word_data);<br />
byte_wr++; //Update buffer pointer<br />
byte_pointer++; //Update global pointer<br />
} else if(i==max_write-1 && ((isOddAddr && sOddByte==0)||(isOddAddr==0 && isOddByte))){<br />
//Last byte not used<br />
//=============================================save last byte<br />
readEEByte( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + byte_pointer + 1,<br />
&word_data);<br />
//============================================================<br />
word_data = (word_data << 8) + buf[byte_wr];<br />
byte_wr++; //Update buffer pointer<br />
byte_pointer++; //Update global pointer<br />
} else{<br />
//Both bytes valid<br />
word_data = ((unsigned int)buf[byte_wr+1] << 8) + buf[byte_wr];<br />
byte_wr+=2; //Update buffer pointer<br />
byte_pointer+=2; //Update global pointer<br />
}<br />
//==================================================================<br />
eraseEEWord( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + 2*word_offset);<br />
writeEEWord( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + 2*word_offset,<br />
&word_data);<br />
//==================================================================<br />
}<br />
return byte_wr; //No. of byte written<br />
}<br />
*eraseEEWord and writeEEWord are implemented in assembly.<br />
.global _eraseEEWord<br />
_eraseEEWord:<br />
push TBLPAG <br />
mov w0, NVMADRU ;w0 = base of eeData<br />
mov w1, NVMADR ;w1 = offset for eeData in word<br />
mov #0x4044, w0 <br />
mov w0, NVMCON ;Set to erase operation<br />
push SR ;Disable global interrupts<br />
mov #0x00E0, w0<br />
ior SR<br />
mov #0x55, w0 ;Write the KEY sequence<br />
mov w0, NVMKEY<br />
mov #0xAA, w0 <br />
mov w0, NVMKEY<br />
bset NVMCON, #15 ;Start the erase cycle, bit 15 = WR<br />
nop<br />
nop<br />
L1: btsc NVMCON, #15 ;while(NVMCONbits.WR)<br />
bra L1<br />
clr w0<br />
pop SR ;Enable global interrupts<br />
pop TBLPAG<br />
return<br />
<br />
.global _writeEEWord<br />
_writeEEWord:<br />
push TBLPAG ;w0 = base of eeData<br />
mov w0, TBLPAG ;w1 = offset for eeData in byte<br />
tblwtl [w2], [w1] ;w2 = pointer to user buffer<br />
mov #0x4004, w0 ;Set to write operation<br />
MOV w0, NVMCON<br />
push SR ;Disable global interrupts<br />
mov #0x00E0, w0<br />
ior SR<br />
mov #0x55, w0 ;Write the KEY sequence<br />
mov w0, NVMKEY<br />
mov #0xAA, w0 <br />
mov w0, NVMKEY<br />
bset NVMCON, #15 ;Start the erase cycle, bit 15 = WR<br />
nop<br />
nop<br />
L2: btsc NVMCON, #15 ;while(NVMCONbits.WR)<br />
bra L2<br />
clr w0<br />
pop SR ;Enable global interrupts<br />
pop TBLPAG<br />
return<br />
<br />
===Simple PWM (Output Compare Module)===<br />
<br />
----<br />
<br />
*The PWM module consists of 8 channels using the output compare module of dsPic.<br />
*These channels are locate at pin 46 (OC1), 49 (OC2), 50 (OC3), 51 (OC4), 52 (OC5), 53 (OC6), 54 (OC7), 55 (OC8). These pins are shared with port D.<br />
*The range of PWM freqeuencies obtainable is 2Hz to 15MHz (See Figure 6.3). Suggested range of operation is 2Hz to 120kHz. The relationship between resolution ''r'' and PWM frequency ''f''<sub>PWM</sub> is given by:<br />
f<sub>PWM</sub> = f<sub>CY</sub>/(Prescale*10<sup>rlog(2)</sup>)<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 6.3 Relationship of Resolution and PWM Frequency<br />
! Resolution (bit) !! Prescale=1 !! Prescale=8 !! Prescale=64 !! Prescale=256<br />
|- <br />
|1||15,000,000 ||1,875,000 ||234,375||58,594 <br />
|- <br />
|2||7,500,000 ||937,500 ||117,188 ||29,297 <br />
|- <br />
|3||3,750,000 ||468,750 ||58,594 ||14,648 <br />
|- <br />
|4||1,875,000 ||234,375 ||29,297 ||7,324 <br />
|- <br />
|5||937,500 ||117,188 ||14,648 ||3,662 <br />
|- <br />
|6||468,750 ||58,594 ||7,324 ||1,831 <br />
|- <br />
|7||234,375 ||29,297 ||3,662 ||916 <br />
|- <br />
|8||117,188 ||14,648 ||1,831||458 <br />
|- <br />
|9||58,594 ||7,324 ||916 ||229 <br />
|- <br />
|10||29,297 ||3,662 ||458 ||114 <br />
|- <br />
|11||14,648 ||1,831 ||229||57 <br />
|- <br />
|12||7,324 ||916 ||114 ||29 <br />
|- <br />
|13||3,662 ||458 ||57 ||14 <br />
|- <br />
|14||1,831 ||229 ||29 ||7 <br />
|- <br />
|15||916 ||114 ||14 ||4 <br />
|- <br />
|16||458 ||57 ||7 ||2 <br />
|-<br />
|}<br />
<br />
====open()====<br />
*A timer (either Timer 2 or 3) is needed to determine the pwm period. The following code uses timer 2 for all 8 channels.<br />
void pwm_open(void){<br />
OC1CON = 0; OC2CON = 0; //Disable all output compare modules<br />
OC3CON = 0; OC4CON = 0;<br />
OC5CON = 0; OC6CON = 0;<br />
OC7CON = 0; OC8CON = 0;<br />
//============================================================<br />
TMR2 = 0; // Clear register<br />
PR2 = 0xFFFF; // Set to Maximum<br />
//============================================================<br />
_T2IF = 0; // Clear interrupt flag<br />
_T2IE = 0 // Enable interrupts<br />
//============================================================<br />
T2CONbits.TCS = 0; // Use internal clock source<br />
T2CONbits.TCKPS = 0; // Prescale Select 1:1<br />
//============================================================<br />
T2CONbits.TON = 1; // Start the timer <br />
}<br />
<br />
====ioctl()====<br />
*User should select the channel and set the pwm period using the functions below before issuing the duty cycle:<br />
char pwm_ioctl(unsigned char request, unsigned long* argp){<br />
unsigned int value;<br />
unsigned char mask;<br />
switch(request){<br />
case PWM_SET_PERIOD:<br />
return setPeriodNPrescale(argp[0]);<br />
case PWM_SELECT_CH:<br />
pwm_channel = argp[0];<br />
mask = 0x01 << pwm_channel;<br />
pwm_status = pwm_status | mask;<br />
return 0;<br />
default:<br />
return -1;<br />
}<br />
}<br />
char setPeriodNPrescale(unsigned long value_ns){<br />
unsigned long ans;<br />
unsigned long long numerator = (unsigned long long)value_ns*SYSTEM_FREQ_MHZ;<br />
int index= -1;<br />
unsigned long denominator;<br />
//-------------------------------------------------<br />
do{<br />
denominator = (unsigned long)1000*pwm_prescale[++index];<br />
ans = (unsigned long)(((long double)numerator/denominator) + 0.5) - 1; //round to nearest int<br />
} while(ans > 0x0000FFFF && index < 3);<br />
//-------------------------------------------------<br />
if(ans > 0x0000FFFF)<br />
return -1;<br />
//-------------------------------------------------<br />
T2CONbits.TON = 0; // Turn off the timer<br />
T2CONbits.TCKPS = index; // Change prescale factor<br />
PR2 = (unsigned int) ans; // Set to Maximum<br />
T2CONbits.TON = 1; // Turn on the timer <br />
//-------------------------------------------------<br />
return 0;<br />
}<br />
<br />
====write()====<br />
*User can change the duty cycle using the following functions<br />
int pwm_write(unsigned long* buf){<br />
if((pwm_status & (0x01 << pwm_channel)) == 0){<br />
return -1; //Channel has not been enabled<br />
}<br />
switch(pwm_channel){<br />
case 0:<br />
OC1RS = calcDCycle(buf[0]); OC1R = OC1RS; <br />
OC1CONbits.OCM = 6; //Simple PWM, Fault pin disabled<br />
break;<br />
case 1:<br />
OC2RS = calcDCycle(buf[0]); OC2R = OC2RS; <br />
OC2CONbits.OCM = 6; //Simple PWM, Fault pin disabled<br />
break;<br />
...<br />
case 7:<br />
OC8RS = calcDCycle(buf[0]); OC8R = OC8RS; <br />
OC8CONbits.OCM = 6; //Simple PWM, Fault pin disabled<br />
break; <br />
default:<br />
return -1;<br />
}<br />
return 4;<br />
}<br />
unsigned int calcDCycle(unsigned long value_ns){<br />
unsigned long long numerator = (unsigned long long)value_ns*SYSTEM_FREQ_MHZ;<br />
unsigned int index = T2CONbits.TCKPS;<br />
unsigned long denominator = (unsigned long)1000*pwm_prescale[index];<br />
return (unsigned int)(((long double)numerator/denominator) + 0.5) - 1; //round to nearest int<br />
}<br />
<br />
====Propagration Delay====<br />
*PWM channels sharing the same timer will have their PWM signals synchronised (i.e. the HIGH state of the duty cycle are all triggered together).<br />
*To introduced delay to the PWM signals, the signal from selected channels may be made to pass through a series of inverters (e.g. 74HC14D). This adds propagation delay to the signal.<br />
*However, as propagration delay of logic gates depends on applied voltage, temperature and load capacitance, the accuracy is low and performance is poor. For accurate delay, delay lines may be used, but they are expensive.<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 6.4 Propagation Delay of [http://www.nxp.com/acrobat_download/datasheets/74HC_HCT14_3.pdf Philips 74HC14D]<sup>[1], [2]</sup><br />
! !! 3.3V !! !! !! 5.0V !! !!<br />
|- <br />
! Number of Gates !! A !! B !! C !! A !! B !! C<br />
|- <br />
| 2 <br />
| 21ns (10.5)|| 23ns (11.5)|| 22ns (11.0)<br />
| 15ns (7.5)|| 14ns (7.0)|| 14ns (7.0)<br />
|-<br />
| 4 <br />
| 45ns (11.3)|| 46ns (11.5)|| 46ns (11.5) <br />
| 30ns (7.5)|| 30ns (7.5)|| 30ns (7.5)<br />
|-<br />
| 6 <br />
| 69ns (11.5)|| 70ns (11.7)|| 72ns (12.0) <br />
| 45ns (7.5)|| 46ns (7.7)|| 47ns (7.8)<br />
|- <br />
|}<br />
[1] Data in specification for 4.5V: Typical 15ns, Maximum 25ns<br><br />
[2] Data in specification for 6.0V: Typical 12ns, Maximum 21ns<br />
<br />
===DSP Library===<br />
<br />
----<br />
*Library functions in <dsp.h> include the following categories: <br />
#Vector<br />
#Window<br />
#Matrix<br />
#Filtering<br />
#Transform<br />
#Control<br />
<br />
====Data Types====<br />
*Signed Fractional Value (1.15 data format)<br />
**Inputs and outputs of the dsp functions adopt 1.15 data format, which consumes 16 bits to represent values between -1 to 1-2<sup>-15</sup> inclusive.<br />
**Bit<15> is a signed bit, positive = 0, negative = 1.<br />
**Bit<14:0> are the exponent bits ''e''.<br />
**Positive value = 1 - 2<sup>-15</sup>*(32768 - ''e'')<br />
**Negative value = 0 - 2<sup>-15</sup>*(32768 - ''e'')<br />
*40-bit Accumulator operations (9.31 data format)<br />
**The dsp functions use the 40 bits accumalators during arithmatic calculations.<br />
**Bit<39:31> are signed bits, positive = 0x000, negative = 0x1FF.<br />
**Bit<30:0> are exponent bits.<br />
*IEEE Floating Point Values<br />
**Fractional values can be converted to Floating point values using: '''fo = Fract2Float(fr);''' for fr = [-1, 1-2<sup>-15</sup>]<br />
**Floating point values can be converted to Fractional values using: '''fr = Float2Fract(fo);''' or '''fr = Q15(fo);''' for fo = [-1, 1-2<sup>-15</sup>]<br />
**Float2Fract() is same as Q15(), except having saturation control. When +ve >= 1, answer = 2<sup>15</sup>-1 = 32767 (0x7FFF). When -ve < -1, answer = -2<sup>15</sup> = -32767 (0x8000)<br />
<br />
===Build-in Library===<br />
<br />
----<br />
*Some assembler operators can only be accessed by inline assembly code, for example, <br />
#Manuipulation of accumulators A and B (add, sub, mul, divide, shift, clear, square)<br />
#Bit toggling<br />
#Access to psv (program space visiblity) page and offset<br />
#Access to table instruction page and offset<br />
*Built-in functions are written as C-like function calls to utilize these assembler operators.<br />
<br />
<br />
==Bootloader Development==<br />
<br />
===Concepts===<br />
*Programming with ICSP is useful when the target board is produced in batch. The producer can download a program even when the chip is on the target board.<br />
*However, ICSP requires an external programmer.<br />
*To allow the user to change the program after production but without the need of an external programmer, bootloader becomes useful.<br />
*Bootloader is a small program installed via ICSP. Everytime the device is reset, the bootloader is run first. The bootloader first detects the default serial channel whether the user wishes to download a new program to the device. If so, the bootloader will pause there, and wait for the user to download the hex file from the PC. The hex file is written to the device via RTSP instructions in the bootloader. If a new download is not necessary, the bootloader redirects to the previously installed user's program.<br />
*The disadvantage of bootloaders is that they consume some of the memory of the device.<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 7.1 Free bootloaders for dsPIC<br />
! Developer<br />
! Source<br />
! Platform<br />
! User Guide<br />
! Remarks<br />
|- valign="top"<br />
| [http://www.ingenia-cat.com/index.php?lang=en ingenia]<br />
| [http://www.ingenia-cat.com/download/iBL.s Assembly]<br />
| [http://www.ingenia-cat.com/download/ingeniadsPICbootloader1.1.zip Windows]<br />
| [http://www.ingenia-cat.com/reference/pdf/iBL.UG.V1.2.pdf pdf]<br />
| <br />
*Works for all dsPIC supporting RTSP<br />
*Auto baudrate detection<br />
*Use about 1.15% of the flash memory space (0xAFFF-0xAE00)/(0xAFFF-0x0100)<br />
*Development of Linux platform is underway<br />
*Modification of code for dsPIC30F5011 is successful<br />
|-valign="top"<br />
| [http://www.etc.ugal.ro/cchiculita/software/picbootloader.htm Tiny]<br />
| [http://www.etc.ugal.ro/cchiculita/software/tinybld191.zip Assembly]<br />
| Windows<br />
| [http://www.etc.ugal.ro/cchiculita/software/tinybldusage.htm Web]<br />
| <br />
*By default, only supports 601X, 601X, 401X, 2010<br />
*Smaller code size than ingenia, but not as easy to modify<br />
|-valign="top"<br />
| [http://www.via.si/software/dsPIC_bootloader/ Elektronika]<br />
| [http://www.via.si/software/dsPIC_bootloader/data/ Hex]<br />
| Windows<br />
| [http://www.via.si/software/dsPIC_bootloader/data/README.txt txt]<br />
| <br />
*Only works for dsPIC30F6014 serial port UART2 at baudrate 57600<br />
|-<br />
|}<br />
<br />
===dsPicBootloader===<br />
<br />
*The bootloader developed by ingenia is open source and it has been modified (see below) to suit our development using dsPic30f5011.<br />
*The bootloader (hereafter called dsPicBootloader) employs the following settings:<br />
# Use U2ART channel<br />
# Use FRC, PLL16<br />
# For 5011, the bootloader is located between 0x00AE00 to 0x00AFFE (512bytes). Refer to C:\Program Files\Ingenia\ingeniadsPICbootloader\ibl_dspiclist.xml after installing the GUI interface.<br />
*Changes made to [http://www.ingenia-cat.com/download/iBL.s assembly code] includes:<br />
1. including p30f5011.gld and p30f5011.inc<br />
.include "p30f5011.inc"<br />
2. changing the config code of UART #0x8420 -> #0x8020<br />
; Uart init<br />
mov '''#0x8020''', W0 ; W0 = 0x8020 -> 1000 0000 0010 0000b<br />
mov W0, U2MODE ; Enable UART, AutoBaud and 8N1<br />
clr U2STA<br />
3. changing the start address 0xAE00 - 0x0100 = 0AD00<br />
.equ CRC, W4<br />
.equ ACK, 0x55<br />
.equ NACK, 0xFF<br />
.equ USER_ADDRESS, 0x0100<br />
.equ START_ADDRESS, '''0xAD00''' ; Relative to 0x0100<br />
4. using Internal FRC and PLL16<br />
config __FOSC, CSW_FSCM_OFF & '''FRC_PLL16''' ;Turn off clock switching and<br />
;fail-safe clock monitoring and<br />
;use the Internal Clock as the<br />
;system clock<br />
5. disabling MCLR (optional)<br />
config __FBORPOR, PBOR_ON & BORV_27 & PWRT_16 & '''MCLR_DIS'''<br />
;Set Brown-out Reset voltage and<br />
;and set Power-up Timer to 16msecs<br />
6. changing all the related registers of U1ART to U2ART, all U1XXX => U2XXX<br />
'''U2MODE, U2STA, U2BRG, U2RXREG, U2TXREG'''<br />
7. changing all the related registers of IC1 to IC2, all IC1XXX => IC2XXX<br />
'''IC2CON, #IC2IF, #IC2IE'''<br />
<br />
===dsPicProgrammer (Java-based Multi-Platformed)===<br />
*Ingenia developed a programmer (PC-side) that works only in Windows environment. The project for Linux environment is currently suspended.<br />
*A simple programmer (hereafter called dsPicProgrammer) written in Java based on the library developed by [http://www.rxtx.org/ RXTX] has been developed here. The programmer supports both Linux and Windows environments, and may be used as a substitution for the official programmer developed by ingenia.<br />
*The programmer has the following specification and limitations:<br />
#Can be used on both Linux and Windows platforms.<br />
#Adjustable baudrate (9600bps to 57600bps<sup>[1]</sup>).<br />
#Support programming of dsPIC30F5011 and dsPIC33FJ128GP306<sup>[2]</sup> devices (Developers may add your devices).<br />
#Protection against overwriting bootloader codes on devices.<br />
#Detection if application program does not have its reset() at user's code start address.<br />
#Reprogramming can be done without powering down the target board, provided the user's program is compliant to that stated below.<br />
#Target board will run the user's program after programming is done.<br />
#Can be used with USB-Serial Cables. Below is a list of tested cable:<br />
::[http://www.prolific.com.tw/eng/Products.asp?ID=59 Prolific PL-2303 USB to Serial Bridge Controller]: [http://www.prolific.com.tw/eng/downloads.asp?ID=31 Driver download]<br />
'''NOTE:'''<br><br />
[1] from version 1.5.2 onwards, the baudrate is increased to 115200bps.<br><br />
[2] only dsPIC30 devices are compatible with the ingenia's programmer. For dsPIC33 devices, the protocol has been modified due to the increased flash size, and the dsPIC33 bootloader can only work with dsPicProgrammer.<br />
<br />
===Special Consideration===<br />
*The bootloader assumes that the user program starts at address 0x100. This is usually the case, but there are always exceptions.<br />
*To ensure that the user program always starts at address 0x100, you can create a customized linker script and customized reset() function as follows:<br />
:*Copy and modify the file named "crt0.s" from the directory "C:\Program Files\Microchip\MPLAB C30\src\pic30" to the project directory and include it.<br />
.section .reset, code //previously .section .libc, code <br />
:*Copy and modify the linkerscript for the device (e.g. p30f5011.gld) to the project directory and include it.<br />
.text __CODE_BASE :<br />
{<br />
*(.reset); //<-insert this line here<br />
*(.handle);<br />
*(.libc) *(.libm) *(.libdsp); /* keep together in this order */<br />
*(.lib*);<br />
*(.text);<br />
} >program<br />
<br />
===Communication Protocol===<br />
<br />
+-------------------+ +-------------------+----------------+<br />
| dsPicProgrammer | | dsPicBootloader | User's Program |<br />
+-------------------+ +-------------------+----------------+<br />
| PC | | Target dsPic |<br />
+-------------------+ +------------------------------------+<br />
| COM PORT |=============| UART |<br />
+-------------------+ +------------------------------------+<br />
<br />
* '''Stage 1: User's Configuation'''<br />
**Select a COM port channel<br />
**Select a baudrate<br />
**Select the user hex file<br />
java -jar dsPicProgrammer.jar COM1 19200 foo.hex<br />
* '''Stage 2: Resetting Target Device'''<br />
**dsPicProgrammer sends a Break character (pull UART-TX to low logic, which is normally high).<br />
**User's program on dsPic detects the break character and reset the chip<br />
::NOTE: The user's program is expected to have the following code in order to enable this function. Otherwise, the target board must be restarted manually.<br />
void _ISR _U2RXInterrupt(void)<br />
{<br />
//No Framming error<br />
if( U2STAbits.FERR == 0)<br />
{<br />
//Normal procedure<br />
}<br />
//Framming error<br />
else<br />
{<br />
if ( U2STAbits.URXDA ){<br />
unsigned char data;<br />
data = (unsigned char) U2RXREG;<br />
if(data == 0x00){<br />
// A break char has been received: <br />
// U2RX has been pulled to zero for more than 13 bits<br />
// This is used to reboot the pic<br />
mdelay(800); //wait for break character to clear<br />
asm("reset"); //software reset<br />
}<br />
} <br />
}<br />
_U2RXIF = 0; //Clear the flag<br />
}<br />
* '''Stage 3: Entering Ingenia's Protocol'''<br />
** Transmission is conducted in 8N1, i.e. 8-bit, no parity, 1 stop-bit<br />
** Communication Protocol is reviewed in [http://www.ingenia-cat.com/reference/pdf/iBL.UG.V1.2.pdf ingenia bootloader user's guide] section 2.1.3. The following summarises the key steps on the PC side (Refer also to section 2.2.2).<br />
::#Autobaud rate detection: dsPicProgrammer continuously sends a character "U" [0x55] via COM port and waits for an acknowledgment character "U", [ACK] = [0x55]<br />
::#Version Control: dsPicProgrammer sends the command character [0x03]. On success, dsPicProgrammer receives 3 characters i) Major Version ii) Minor Version iii) Acknowledgment [0x55]<br />
::#Device ID Monitoring: dsPicProgrammer sends the read command character [0x01] + 24-bit address [High][Medium][Low] (0xFF0000). Then, it receives 4-byte data [High][Medium][Low][ACK]<br />
::#Load the user hex file and check integrity<br />
::#Start Programming: dsPicProgrammer issues the write command character [0x02] + 24-bit address [High][Medium][Low]+ Number of bytes [N] + [data 0] + [data 1] + ... + [data N-1] + [CRC]=(INTEL HEX8 Checksum - Sum modulo 256) and receives [ACK] or [NACK] = [0xFF]<br />
::NOTE: Writing is in row mode access (i.e. erase and write a whole row, each row has 32 instructions, or 96 bytes because each instruction has 24 bits)<br />
* '''Stage 4: Goto User's Program'''<br />
**dsPicProgrammer sends the goto user code command [0x0F]<br />
<br />
<br />
==USB-RS232 Bridge==<br />
<br />
*As USB ports are becoming more and more common, COM ports and Parallel ports may be redundant in the next few years. This section explore the possibilities of programming the target board through a USB port.<br />
*There are two options:<br />
#Use an external USB/RS232 adaptor, the driver will emulate a virtual COM port, such as [http://www.prolific.com.tw/eng/downloads.asp?ID=31 Prolific] and [http://www.ftdichip.com/Drivers/VCP.htm FDTI]. Ingenia has tested its bootloader with some USB-232 manufacturers (silabs, FTDI, etc..). However, the programming failed with our Prolific adapter. Application program may use [http://java.sun.com/products/javacomm/ JavaComm API] (javax.comm) and/or [http://www.rxtx.org/ RXTX] to drive the COM port.<br />
#Modified the bootloader program on PC to support USB communication. e.g. using [http://jusb.sourceforge.net/ jUSB] and [http://javax-usb.org/ JSR-80] (javax.usb). External circuits such as PIC18F4550 and MAX232 are required.<br />
<br />
|--User's App.--|-------Device Manager------|-------USB-RS232 Interface------|---dsPIC---|<br />
Option 1:<br />
+-------------+ +----------+ +----------+ +---+ +------------+ +-----+ +--------+<br />
| Application |--| JavaComm |--| Virtual |==|USB|--| FDTI |--|RS232|==| Target |<br />
| Program | | RXTX | | COM Port | +---+ | Circuitary | +-----+ | Board |<br />
+-------------+ +----------+ +----------+ +------------+ +--------+<br />
Option 2:<br />
+-------------+ +--------+ +---+ +------------+ +-----+ +--------+<br />
| Application |----------| JSR-80 |==========|USB|--| PIC18F4550 |--|RS232|==| Target |<br />
| Program | | jUSB | +---+ | MAX232 | +-----+ | Board |<br />
+-------------+ +--------+ +------------+ +--------+<br />
<br />
*Currently, when RXTX is incorporated with JavaComm API, operating systems supported include Linux, Windows, Mac OS, Solaris and other operating systems. On the other hand, jUSB and JSR-80 only works for linux.<br />
<br />
===FDTI Chipset===<br />
*FT232RL communicates with PC via USB to provide 1 UART channel.<br />
*Datasheet can be downloaded [http://www.ftdichip.com/Documents/DataSheets/DS_FT232R.pdf here]. <br />
**Refer to Fig. 11 (Page 19) for Bus Powered Configuration.<br />
**Refer to Fig. 16 (Page 24) for for UART TTL-level Receive [RXD -> 1], Transmit [TXD -> 4], Transmit Enable [CBUS2/TXDEN -> 3]. Omit Receive Enable [CBUS3/PWREN#] and use [CBUS2/TXDEN -> 2] <br />
**Refer to Fig. 15 (Page 23) for LED Configuration: [CBUS0/TXLED#] and [CBUS1/RXLED#]<br />
*Virtual COM Port Drivers can be downloaded [http://www.ftdichip.com/Drivers/VCP.htm here].<br />
<br />
<br />
==Programming the Device==<br />
<br />
===Requirements===<br />
*Hardware<br />
#PC with COM port (Windows XP Installed for MPLAB)<br />
#ICD2 Programmer<br />
#Target Board<br />
#5V Power Supply<br />
<br />
*Software<br />
#[http://ww1.microchip.com/downloads/en/DeviceDoc/MP750.zip MPLAB IDE v7.50]: v7.60 is not compatible with our current [http://www.sure-electronics.com/ ICD2 Programmers]. There are consistent "Devices cannot be founded" warnings.<br />
#[http://chungyan5.no-ip.org/websvn/listing.php dsPicProgrammer] ('''dsPicProgrammer.jar''')<br />
#[http://users.frii.com/jarvi/rxtx/download.html RXTX driver]: download and upzip rxtx-2.1-7-bins-r2.zip (Final)<br />
<br />
*Files<br />
#[http://chungyan5.no-ip.org/websvn/listing.php dsPicBootloader] ('''bl_5011.hex'''). Original assembly code by ingenia can be downloaded from [http://www.ingenia-cat.com/download/iBL.s here].<br />
#Application hex file (e.g. '''app.hex''')<br />
<br />
===Loading Bootloader (Once only)===<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 9.1 Loading Bootloader<br />
! Step !! Remarks <br />
|-valign="top"<br />
| Install [http://ww1.microchip.com/downloads/en/DeviceDoc/MP750.zip MPLAB IDE] || <br />
*Do '''NOT''' connect ICD 2 (via USB) to PC<br />
*Execute '''MPLAB vX.XX Install.exe'''<br />
|-valign="top"<br />
| Install USB Driver ||<br />
*Follow the instruction in (C:\Program Files\Microchip\MPLAB IDE\ICD2\Drivers\Ddicd2.htm)<br />
|-valign="top"<br />
| Select Target Chip ||<br />
*Run MPLAB IDE on PC<br />
*Select: Configure>Select Devices...<br />
*Choose dsPIC30F5011<br />
|-valign="top"<br />
| Target <-> ICD 2 ||<br />
*Use six pin cable. Beware of the pin assignments. Only pin 1 - 5 should be used.<br />
*Place Jumper on target board (if any). The Jumper connects target V<sub>cc</sub> to ICD 2.<br />
*Do '''NOT''' power-up the target.<br />
|-valign="top"<br />
| ICD 2 <-> PC ||<br />
*Plug-in ICD 2 to PC via USB cable<br />
*Power-up the target.<br />
*Select: Programmer>Select Programmer>MPLAB ICD 2<br />
*If this is the first time the ICD 2 is connected to PC, MPLAB IDE will automatically download the required OS to ICD 2, wait until it has finished<br />
*If you have not connected and powered up the target, you might see Warnings on invalid device IDs, and/or running self tests.<br />
*See results of self test if necessary: Programmer>Settings, Status Tab. Refer to [http://ww1.microchip.com/downloads/en/DeviceDoc/51331B.pdf ICD2 User's Guide] Chapter 7.<br />
|-valign="top"<br />
| Load Bootloader ||<br />
*Select: File>Import...<br />
*Select '''bl_5011.hex'''<br />
|-valign="top"<br />
| Start Programming ||<br />
*Select: Programmer>Program<br />
|-valign="top"<br />
| Finishing ||<br />
*Power-down the Taget<br />
*Select: Programmer>Select Programmer>None<br />
*Unplug USB cable<br />
|-<br />
|}<br />
<br />
===Loading Firmware===<br />
<!--using Firefox-File-Page_Setup-Format-Scale-85% to print --><br />
====Java Environment Setup====<br />
*Download and install the latest JDK or JRE<br />
**Available from [http://java.sun.com/javase/downloads/index.jsp Sun Microsystems] (e.g. JDK 6 Update 3)<br>[[Image:1 1 java.JPG]]<br><br />
*Download and Extract RXTX Driver <br />
**Available from [http://users.frii.com/jarvi/rxtx/download.html RXTX] <br />
**File: rxtx-2.1-7-bins-r2.zip (Final)<br />
**Extract the files using software such as WinRAR<br>[[Image:1 2 rxtx.JPG]]<br><br />
*Copy RXTXcomm.jar<br />
**To C:\Program Files\Java\X\lib\ext (under the latest jre, e.g. X = jre1.6.0_03)<br>[[Image:1 3 rxtxcomm.JPG]]<br><br />
*Copy rxtxSerial.dll<br />
**To C:\Program Files\Java\X\bin (under the lastest jre, e.g. X = jre1.6.0_03)<br />
**For Linux users, copy librxtxSerial.so to /jre/lib/[machine type] (i386 for instance)<br>[[Image:1 4 rxtxserial.JPG]]<br><br />
*Download dsPicProgrammer <br />
**Available from [http://chungyan5.no-ip.org/vc here]<br />
**Expand the latest tag under dsPicProgrammer<br />
**File: dsPicProgrammer.jar<br>[[Image:1 5 dspicprogrammer.JPG]]<br><br />
**Save the file (dsPicProgrammer.jar) and your hex file (foo.hex) to your local directory (e.g. C:\dsPicProgrammer\)<br>[[Image:1 6 dspicprogrammer2.JPG]]<br><br />
=====directly download this [http://chungyan5.no-ip.org/open_data/electronic_computer/platforms/dspic/dsPicProgrammer/dsPicProgrammer1.5.2.zip package]=====<br />
<br />
====Download Firmware====<br />
*Start a Command Prompt<br />
**Start -> Run<br>[[Image:2 1 run.JPG]]<br><br />
**Enter cmd<br>[[Image:2 2 cmd.JPG]]<br><br />
*Run dsPicProgrammer<br />
**Make sure your device is connected through a "Direct RS232 Cable" to PC Serial Port. <br />
**Change to the directory where dsPicProgrammer.jar is located and run the command:<br />
***[path/to/java/]java -Djava.library.path=[path/to/rxtxlib] -jar dsPicProgrammer.jar COM1 57600 foo.hex<br />
****for example, jre\bin\java -Djava.library.path=.\rxtx\bin -jar dspicProgrammer.jar COM1 57600 foo.hex<br />
***Or directly using dsPicProgrammer.bat COM1 57600 foo.hex(Windows)<br />
***java -jar dsPicProgrammer.jar /dev/ttyS0 57600 foo.hex (Linux)<br />
:::where COM1 is your COM Port ID<br />
:::57600 is communication speed [in bps]<br />
:::foo.hex is your firmware new file<br />
::[[Image:2 3 command.JPG]]<br />
**When the program prompt you for an input, press y:<br>[[Image:2 4 prompt.JPG]]<br><br />
**If communication can be established, you should see something like this:<br>[[Image:2 5 progress.JPG]]<br><br />
**Wait until programming is completed.<br>[[Image:2 6 complete.JPG]]<br><br />
**after all completed, power OFF your device, then power ON again, enjoy your new updated.<br />
<br />
====Troubleshooting====<br />
*Invalid COM Port<br />
**In case of selecting an invalid COM port, you should see the error message:<br>gnu.io.NoSuchPortException: Choosing COM Port Error<br>[[Image:3 1 com err.JPG]]<br><br />
*Missing firmware file<br />
**In case of selecting a firmware file that does not exist, you should see the error message:<br>java.io.FileNotFoundException: foo1.hex <The system cannot find the file specified><br>[[Image:3 2 file err.JPG]]<br><br />
*Missing RXTX driver<br />
**In case of missing the RXTX driver, you should see the error message:<br>Exception in thread “main” java.lang.NoClassDefFoundError: gnu/io/UnsupportedCommOperationException<br>[[Image:3 3 rxtx err.JPG]]<br><br />
<br />
==Remote Access==<br />
*At the moment, local devices (e.g. EEPROM, ADC, DAC, etc.) can only be accessed locally through POSIX functions such as open(), read(), write(), ioctl().<br />
*However, a client may need to access these devices on a remote server. This section reviews the background and gives some ideas on its possible implementation.<br />
<br />
===Requirements===<br />
*A remote file access protocol, to transfer "files" (i.e. device's data) such as:<br />
#[http://en.wikipedia.org/wiki/FTP File Transfer Protocol] (FTP): Required files are copied from sever to client for manipulation<br />
#[http://en.wikipedia.org/wiki/Remote_Shell Remote Shell] (RSH): Required files are copied from sever to client for manipulation<br />
#[http://en.wikipedia.org/wiki/Network_File_System_%28Sun%29 Network File System] (NFS): Required files are manipulated on sever<br />
*An API to access files using a selected protocol, such as:<br />
#[http://www.die.net/doc/linux/man/man2/lam_rfposix.2.html lam_rfposix]: A POSIX-like remote file service for Local Area Multicomputer<br />
#API employed by VxWorks: [http://en.wikipedia.org/wiki/VxWorks VxWorks] is a Unix-like real-time operating system, commonly used for embedded systems.<br />
<br />
===API Reference for VxWorks===<br />
*Reference:<br />
**[http://www.windriver.com/vxworks/ VxWorks Official Website]<br />
**[http://www-cdfonline.fnal.gov/daq/commercial/ OS Libraries API Reference]<br />
*Related Libraies<br />
**netDrv (netDrv.h): an API using FTP or RSH<br />
**nfsDrv (nfsDrv.h): an API using NFS<br />
<br />
<br />
==Conversion to dsPIC33F Devices==<br />
*This section discusses the conversion required from dsPIC30F5011 to dsPIC33FJ128GP306.<br />
*Refer to official document [http://ww1.microchip.com/downloads/en/DeviceDoc/70172A.pdf dsPIC30F to dsPIC33F Conversion Guidelines] (DS70172A).<br />
*Note that this section does not mainly intend to introduce the new functionalities of dsPIC33F devices. It only serves the purpose to summarise the major (if not minimum) changes required to port the setup of dsPIC30 to dsPIC33 devices.<br />
<br />
===Hardware===<br />
*dsPIC33 operates at voltage of 3.3V. A voltage regulator, such as [http://www.national.com/ds.cgi/LM/LM3940.pdf LM3940] can be used to convert 5V supply to 3.3V.<br />
*A 1uF capacitor has to be placed at pin 56 (previously V<sub>SS</sub>, now V<sub>DDCORE</sub>).<br />
<br />
===Software===<br />
<br />
====Configuration Bits====<br />
<br />
----<br />
*dsPIC33 can operate at 40MIPs at maximum. To configure the device using internal FRC, replace the configuration bits setting as follows:<br />
_FOSCSEL(FNOSC_FRCPLL); // FRC Oscillator with PLL<br />
_FOSC(FCKSM_CSDCMD & OSCIOFNC_ON & POSCMD_NONE); <br />
// Clock Switching and Fail Safe Clock Monitor is disabled<br />
// OSC2 Pin Function: OSC2(RC15) as Digital IO<br />
// Primary Oscillator Mode: Disabled<br />
_FWDT(FWDTEN_OFF); // Watchdog Timer Enabled/disabled by user software <br />
*Configure on-chip PLL at runtime as follows (at start of main function):<br />
_PLLDIV = 38; // M=40: PLL Feedback Divisor bits<br />
CLKDIV = 0; // N1=2: PLL VCO Output Divider Select bits<br />
// N2=2: PLL Phase Detector Input Divider bits<br />
OSCTUN = 22; // Tune FRC oscillator, if FRC is used; <br />
// 0: Center frequency (7.37 MHz nominal)<br />
// 22: +8.25% (7.98 MHz)<br />
RCONbits.SWDTEN = 0; // Disable Watch Dog Timer<br />
while(OSCCONbits.LOCK != 1); // Wait for PLL to lock<br />
<br />
====UART====<br />
<br />
----<br />
*No change is required.<br />
<br />
====I2C====<br />
<br />
----<br />
*dsPIC33 supports upto 2 I<sup>2</sup>C devices. As a result, replace all I<sup>2</sup>C related registers with xxI2Cyy to xxI2C'''1'''yy. For examples:<br />
_SI2C1IF = 0; //Clear Slave interrupt<br />
_MI2C1IF = 0; //Clear Master interrupt<br />
_SI2C1IE = 0; //Disable Slave interrupt<br />
_MI2C1IE = 0; //Disable Master interrupt<br />
I2C1BRG = I2C_BRG; // Configure Baud rate<br />
I2C1CONbits.I2CEN = 1;<br />
...<br />
etc.<br />
<br />
====ADC====<br />
<br />
----<br />
*The ADC in dsPic33 is significantly different from that in dsPic30. Specifically, ADC in dsPic33 uses DMA to buffer the adc data. Replace the open, interrupt routine, add and remove codes as follows:<br />
<br />
unsigned int adc_bufA[ADC_MAX_CH] __attribute__((space(dma),aligned(256)));<br />
unsigned int adc_bufB[ADC_MAX_CH] __attribute__((space(dma),aligned(256)));<br />
unsigned int* ADC16Ptr; //Pointer to ADC register buffer, <br />
unsigned char adc_ch_select = 0; //Pointer to channel to be read from<br />
unsigned char adc_data_ready = 0; //Indicate if RAM data is ready for output<br />
unsigned int which_dma = 0; //indicate which adc_buf to be used<br />
<br />
void adc_open(void)<br />
{<br />
// Configure interrupt<br />
_AD1IF = 0; //clear ADC interrupt flag<br />
_AD1IE = 0; //disable adc interrupt<br />
AD1CHSbits.CH0NA = 0;<br />
// Configure analog i/o <br />
_TRISB0 = 1;<br />
_TRISB1 = 1; <br />
AD1PCFG = 0xFFFC; //Enable AN0 (Vref+) and AN1 (Vref-)<br />
AD1PCFGH = 0xFFFF; //AN16-AN31: Disabled<br />
// Configure scan input channels <br />
AD1CSSL = 0x0003; //0 => Skip, 1 => Scan<br />
AD1CSSH = 0x0000; //Skipping AN16-AN31<br />
// ADCCON4:<br />
AD1CON4bits.DMABL = 0; // Each buffer contains 1 word<br />
// ADCCON3:<br />
AD1CON3bits.SAMC = 1; //1TAD for sampling time<br />
AD1CON3bits.ADRC = 0; //Use system clock<br />
AD1CON3bits.ADCS = ADC_ADCS; //each conversion requires 14TAD<br />
// ADCCON2:<br />
AD1CON2bits.VCFG = 3; //External Vref+, Vref-<br />
AD1CON2bits.CSCNA = 1; //Scan input<br />
AD1CON2bits.SMPI = 1; //2 channels are scanned<br />
// ADCCON1:<br />
AD1CON1bits.FORM = 0; //[0:integer]; [2 fractional]; [3 siged fractional]<br />
AD1CON1bits.SSRC = 7; //auto covert, using internal clock source<br />
AD1CON1bits.ASAM = 1; //auto setting of SAMP bit<br />
AD1CON1bits.AD12B = 1; //12-bit, 1-channel ADC operation<br />
AD1CON1bits.ADDMABM = 0; // DMA buffers are built in scatter/gather mode<br />
AD1CON1bits.ADON = 1; // Turn on the A/D converter<br />
// DMA0 Configuration:<br />
DMA0CONbits.AMODE = 2; // Configure DMA for Peripheral indirect mode<br />
DMA0CONbits.MODE = 2; // Configure DMA for Continuous Ping-Pong mode<br />
DMA0PAD=(int)&ADC1BUF0; <br />
DMA0CNT = 1; // generate dma interrupt every 2 samples <br />
// same as SMPI because only 1 dma buffer per channel <br />
DMA0REQ = 13; // Select ADC1 as DMA Request source<br />
DMA0STA = __builtin_dmaoffset(adc_bufA); <br />
DMA0STB = __builtin_dmaoffset(adc_bufB);<br />
_DMA0IF = 0; // Clear the DMA interrupt flag bit<br />
_DMA0IE = 1; // Set the DMA interrupt enable bit<br />
DMA0CONbits.CHEN=1; // Enable DMA<br />
}<br />
<br />
void _ISR _DMA0Interrupt(void)<br />
{<br />
ADC16Ptr = (which_dma == 0)? adc_bufA : adc_bufB; //Update pointer<br />
adc_data_ready = 1;<br />
which_dma ^= 1; //Next buffer to be used<br />
_DMA0IF = 0; //Clear the DMA0 Interrupt Flag<br />
}<br />
<br />
static void adcAdd(unsigned char ch){<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
TRISB = TRISB | mask;<br />
AD1CSSL = AD1CSSL | mask; <br />
AD1PCFG = ~AD1CSSL;<br />
AD1CON2bits.SMPI++; //take one more sample per interrupt<br />
DMA0CNT++; <br />
}<br />
<br />
static void adcRm(unsigned char ch){<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
AD1PCFG = AD1PCFG | mask;<br />
AD1CSSL = ~AD1PCFG;<br />
AD1CON2bits.SMPI--; //take one less sample per interrupt<br />
DMA0CNT--; <br />
}<br />
<br />
====EEPROM====<br />
<br />
----<br />
*There is no EEPROM in dsPIC33 devices. Please consider to use an external EEPROM using I<sup>2</sup>C communication.<br />
<br />
====Simple PWM====<br />
<br />
----<br />
*No change is required.<br />
<br />
===Memory Map for dsPIC33FJ128GP306===<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 11.1 Memory Location<br />
! Type !! Start Address !! End Address !! Size<br />
|-valign="top"<br />
| Flash || 0x000000 ||0x0157FF || 86K<sup>[1]</sup><br />
|-valign="top"<br />
| +--Flash: Reset Vector || 0x000000 ||0x000003 || 4<br />
|-valign="top"<br />
| +--Flash: Interrupt Vector Table || 0x000004 ||0x0000FF || 252<br />
|-valign="top"<br />
| +--Flash: Alternate Vector Table || 0x000104 ||0x0001FF || 252<br />
|-valign="top"<br />
| +--Flash: User Program || 0x000200 ||0x0157FF || 85.5K<br />
|-valign="top"<br />
| Programming Executive || 0x800000 || 0x800FFF || 4K<sup>[1]</sup><br />
|-valign="top"<br />
| Config Registers || 0xF80000 || 0xF80017 || 24<br />
|-valign="top"<br />
| Device ID (0xE5) || 0xFF0000 || 0xFF0003 || 4<br />
|-<br />
|}<br />
[1] Each address is 16-bit wide. Every two addresses correspond to a 24-bit instruction. Each even address contains 2 valid bytes; each odd address contains 1 valid byte plus 1 phathom byte.<br><br />
<br />
===Custom Linker Script to Maximize Space for Constant Data===<br />
*Constant data declared using keyword '''const''' will be stored in the .const section in the flash memory.<br />
*Normally, during compilation, the linker will assign these data after the program code (.text section).<br />
*Since .const is accessed by auto-psv function, to maximize the space for constant data (32kb), the .const section needs to be aligned at 0x80000 boundary.<br />
*This requires the following change in linker script:<br />
<br />
__CONST_BASE = 0x8000;<br />
<br />
.text __CODE_BASE :<br />
{<br />
*(.reset);<br />
*(.handle);<br />
*(.libc) *(.libm) *(.libdsp); /* keep together in this order */<br />
*(.lib*);<br />
/* *(.text); deleted to maximize space for const data */<br />
} >program<br />
<br />
.const __CONST_BASE :<br />
{<br />
*(.const);<br />
} >program<br />
<br />
*If your program is large, after this change in linker script, function calls may involve large jump in the memory map (>32kB). As a result, you may need to enable the large code and large memory model during compilation. In such case, use the following options in your build path:<br />
-mlarge-code -mlarge-data<br />
*Meanwhile, functions that are defined in the standard C libraries, but are replaced with your own implementations (e.g. I/O stubs: open(), read(), write(), lseek(), ioctl() etc.) may have the following linker error:<br />
/usr/pic30-elf/lib//libc-elf.a(fflush.eo)(.libc+0x3c): In function '.LM11':<br />
: Link Error: relocation truncated to fit: PC RELATIVE BRANCH _write<br />
/usr/pic30-elf/lib//libc-elf.a(fclose.eo)(.libc+0x42): In function '.LM18':<br />
: Link Error: relocation truncated to fit: PC RELATIVE BRANCH _close <br />
*To resolve the problem, you need to place the functions in the .libc section rather than in the .text section, like this:<br />
#define LIBC_CODE_LOC __attribute__ ( (section(".libc")))<br />
<br />
int LIBC_CODE_LOC open(const char *pathname, int flags){ ... }<br />
int LIBC_CODE_LOC close(int fd){ ... }<br />
int LIBC_CODE_LOC write(int fd, void* buf, int count) { ... }<br />
int LIBC_CODE_LOC read(int fd, void* buf, int count) { ... }<br />
int LIBC_CODE_LOC ioctl(int fd, int request, void* argp) { ... }<br />
int LIBC_CODE_LOC lseek(int fd, int offset, int whence) { ... }<br />
<br />
===dsPicBootloader and dsPicProgrammer===<br />
*RTSP for dsPIC33F is different from dsPIC30F.<br />
**Row size changes from 32 instructions (96bytes) to 64 instructions (192 bytes)<br />
**Erase operation changes from 1 row to 8 rows<br />
**No EEPROM<br />
*With regards to the above changes, dsPicBootloader and dsPicProgrammer has been modified. In particular, dsPicProgrammer can be used to program both dsPic30F and dsPic33F devices (Yet, dsPic33F is no longer compatible with Ingenia's programmer). You can easily add your devices to the source code.<br />
<br />
==Downloads==<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 12.1 Related software download links for dsPicBootloader and dsPicProgrammer<br />
! Program<br />
! Site 1<br />
! Site 2<br />
! Remarks<br />
|- valign="top"<br />
| JDK<br />
| [http://java.sun.com/javase/downloads/index.jsp website]<br />
| <br />
| Download latest JDK<br />
|- valign="top"<br />
| RXTX<br />
| [http://users.frii.com/jarvi/rxtx/download.html website]<br />
| <br />
| Download rxtx-2.1-7-bins-r2.zip or later<br />
|- valign="top"<br />
| dsPicBootloader<br />
| [http://chungyan5.no-ip.org/vc click]<br />
| [http://www.opencircuits.com/images/a/a7/DsPicBootloader_1_3_1.zip click (v1.3)]<br />
| Under "dsPicBootloader/", download bl_5011.s or bl_j128gp306.s<br />
|-valign="top"<br />
| dsPicProgrammer<br />
| [http://chungyan5.no-ip.org/vc click]<br />
| [http://www.opencircuits.com/images/9/9e/DsPicProgrammer_1_3_5.zip click (v1.3.5)]<br />
| Under "dsPicProgrammer/", dowload dsPicProgrammer.jar<br><br>Alternatively, if you want to compile yourself or modify the source code, download <br>all source files under "dsPicProgrammer/" '''plus''' RdFileIntelHex.java under <br>"IntelHexPaser/tags/0.02.00/".<br>You should also install RXTX on your local machine as recommended in the readme file.<br />
|- valign="top"<br />
| Ingenia's bootloader<br />
| [http://www.ingenia-cat.com/en/downloads.php website]<br />
| <br />
| Download original ingenia's bootloader<br />
|-<br />
|}</div>Yanhttp://www.opencircuits.com/index.php?title=RS232_RS485_USB_Converter_Board&diff=15609RS232 RS485 USB Converter Board2008-06-11T07:22:48Z<p>Yan: /* Circuit and PCB */ update links here</p>
<hr />
<div>==Features==<br />
<!--<graphviz><br />
digraph blks_conn {<br />
mcu [shape=box, label="mcu"];<br />
RS232 [shape=box, label="rs232"];<br />
rs485_422 [shape=box, label="rs485/422"];<br />
usb [shape=box, label="slave usb"];<br />
comm [shape=box, label="common wires"];<br />
mcu -> comm [dir = both];<br />
comm -> RS232 [dir = both];<br />
comm -> rs485_422 [dir = both];<br />
comm -> usb [dir = both];<br />
}<br />
</graphviz>--><br />
*for low traffic and low speed application<br />
*mcu, RS232, RS485/RS422, slave usb all can be interchangeable.<br />
*usb side<br />
**support platform in linux with usb driver<br />
**simulated uart programming in application level<br />
*rs232 to rs485 side<br />
**Tested max. baudrate is 115200(i assume more high baudrate can be accepted, but i have not tested)<br />
<br />
<br />
==Technical==<br />
<br />
<br />
===RS232===<br />
*[http://www.realhamradio.com/tac32-interface.htm RS232 Circuit examples]<br />
<br />
<br />
===USB===<br />
*Host Computer Setting for usb connection<br />
**[http://www.ftdichip.com/ Using Solution from FTDI Chips]<br />
**[http://www.ftdichip.com/Drivers/FT2232CDrivers.htm#VCP Linux USB Driver and its usb api, a simulate uart api match to usb api FOR ftdichip]<br />
**References<br />
***[http://www.beyondlogic.org/usb/ftdi.htm beyondlogic for ftdi]<br />
***[http://ftdi-usb-sio.sourceforge.net/ sourceforge usb driver for ftdi]<br />
*chips<br />
**[http://chungyan5.no-ip.org/WebServerDocs/open_data/KnowledgeDb/ComputerSysDevelopment/apps/comm/converter/ds2232c_15.pdf ds2232c]<br />
<br />
<br />
===RS485===<br />
*chips<br />
**Linear Technology Corp., LTC2859 and LTC2861<br />
**[http://chungyan5.no-ip.org/WebServerDocs/open_data/KnowledgeDb/ComputerSysDevelopment/apps/comm/converter/DS3695.pdf DS3695]<br />
<br />
<br />
===Circuit and PCB===<br />
*[http://chungyan5.no-ip.org/vc/converter/ gEDA Project Files]<br />
:OR [[Media:Converter.zip|Download here, not always updated]]<br />
:gEDA libraries can be download [http://www.opencircuits.com/PCB_Footprints here] or [http://chungyan5.no-ip.org/open_data/electronic_computer/eda/geda/libs more updated], then modify the gafrc inside converter/<br />
*We have components and PCB, Or some have already soldered, if needed email to us: [mailto:yan@amonics.com yan]<br />
<br />
==ToDo==<br />
*get a usb chips to uart, which with linux driver<br />
**MCT P87C52UBAA(http://pfranc.com/usb/usb.mhtml)<br />
**cypress, PSoC with USB<br />
*linux driver<br />
**driver in linux : http://ftdi-usb-sio.sourceforge.net/<br />
**usb in linux guide : http://www.linux-usb.org/USB-guide/book1.html<br />
*get a usb to rs232/485 converter driver<br />
**driver in windows : http://www.hexin-tech.com.cn/<br />
[[Category:Projects]]</div>Yanhttp://www.opencircuits.com/index.php?title=DsPIC30F_5011_Development_Board&diff=14583DsPIC30F 5011 Development Board2008-02-20T07:25:56Z<p>Yan: /* Download Firmware */ remind user to connect RS232 cable bet. device and PC</p>
<hr />
<div>==Introduction==<br />
<br />
===Features of dsPIC30F5011===<br />
*2.5 to 5V <br />
*Up to 30MIPs<br />
*High current/sink source I/O pins: 25mA<br />
*DSP Instruction Set<br />
*Dual programming techniques: ICSP and RTSP<br />
*UART: up to 2 modules<br />
*I<sup>2</sup>C: up to 1Mbps<br />
*10-bit A/D, 1.1 Msps <br />
*12-bit A/D, 200 ksps<br />
*44K flash (66Kb), 4Kb RAM, 1Kb EEPROM<br />
*No DAC<br />
*Pin-to-pin compatible with other dsPICs<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 1.1 Comparison with Compatible dsPICs<br />
! dsPic !! Price<br>US$ !! MIPs<br />
! Flash<br>(kB)!! RAM<br>(kB) !! EEPROM<br>(kB)<br />
! I/O !! ADC<br>12-bit !! IC !! OC !! Motor<br>Ctrl !! Timers<br />
! QEI !! UART !! SPI !! I2C !! CAN !! Codec<br />
|- <br />
| 30F5011 || 5.91 || 30<br />
| 66 || 4 || 1<br />
| 52 || 16 || 8 || 8 || 0 || 5x16bit<br>2x32bit<br />
| 0 || 2 || 2 || 1 || 2 || 1<br />
|-<br />
| 30F6011A || 7.73 || 30<br />
| 132 || 6 || 2<br />
| 52 || 16 || 8 || 8 || 0 || 5x16bit<br>2x32bit<br />
| 0 || 2 || 2 || 1 || 2 || 0<br />
|-<br />
| 30F6012A || 7.85 || 30<br />
| 144 || 8 || 4<br />
| 52 || 16 || 8 || 8 || 0 || 5x16bit<br>2x32bit<br />
| 0 || 2 || 2 || 1 || 2 || 1<br />
|- <br />
| 33FJ128GP206 || 4.62 || 40<br />
| 128 || 8 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 1 || 0 || 1<br />
|-<br />
| 33FJ128GP306 || 4.81 || 40<br />
| 128 || 16 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 2 || 0 || 1<br />
|-<br />
| 33FJ128GP706 || 5.49 || 40<br />
| 128 || 16 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 2 || 2 || 1<br />
|-<br />
| 33FJ128MC506 || 4.97 || 40<br />
| 128 || 8 || 0<br />
| 53 || 16 || 8 || 8 || 8 || 9x16bit<br>4x32bit<br />
| 1 || 2 || 2 || 2 || 1 || 0<br />
|-<br />
| 33FJ128MC706 || 5.38 || 40<br />
| 128 || 16 || 0<br />
| 53 || 16 || 8 || 8 || 8 || 9x16bit<br>4x32bit<br />
| 1 || 2 || 2 || 2 || 1 || 0<br />
|-<br />
| 33FJ256GP506 || 6.11 || 40<br />
| 256 || 16 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 2 || 1 || 1<br />
|-<br />
|}<br />
<br />
===Web Page===<br />
*[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2529&param=en024856 Microchip Official Website]<br />
<br />
===Forum===<br />
*[http://direct.forum.microchip.com/default.aspx Microchip]: Official forum by Microchip<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=49 MPLAB ICD 2]: Subforum on ICD 2 programmer<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=57 MPLAB IDE]: Subforum on IDE<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=101 MPLAB C30 Compiler, ASM30, Link30 forum]: Subforum on C compiler. Refer to [http://ww1.microchip.com/downloads/en/DeviceDoc/C30_Users_Guide_51284e.pdf MPLAB C30 C Compiler User's Guide] Chapter 3<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=153 dsPIC30F Topics]: Subformum on dsPIC30F<br />
*[http://www.gnupic.org/ GNUPIC]: Discussion on PIC in Linux Systems<br />
**[http://www.linuxhacker.org/cgi-bin/ezmlm-cgi?1:dds:5443#b Debian]<br />
*[http://www.htsoft.com/forum/all/ubbthreads.php/Cat/0/C/6 HI-TECH Software Forum]: Discussion on dsPICC, a C compiler developed by HI-TECH<br />
*[http://piclist.com/techref/piclist/index.htm PICList]: Discussion on older PIC systems (not dsPIC)<br />
*[http://groups.google.com/group/pickit-devel PicKit]: Discussion on PICkit/PICkit 2 programmers<br />
*[http://sourceforge.net/forum/forum.php?forum_id=382005 FreeRTOS Real Time Kernel]: Open Discussion and Support on FreeRTOS <br />
<br />
===References===<br />
*dsPIC30F<br />
**[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2574 dsPIC30F Family Reference Manual Sections]: Contains detailed descriptions on dsPIC30F register definitions and example codes<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80169E.pdf dsPIC30F Family Reference Manual Errata (Use with revision 70046B only)]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70116F.pdf dsPIC30F5011, dsPIC30F5013 Data Sheet]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80210e.pdf dsPIC30F5011/5013 Rev. A1/A2 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80223D.pdf dsPIC30F5011/5013 Rev. A3 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70102G.pdf Flash Programming Specification]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70157B.pdf dsPIC30F Programmer's Reference Manual]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80170a.pdf dsPIC30F Programmer's Reference Manual Errata (use with revision DS70030E only)]<br />
<br />
*dsPIC33F<br />
**[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2573 dsPIC33F Family Reference Manual Sections]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70165E.pdf dsPIC33F Family Data Sheet]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80279B.pdf dsPIC33F Rev. A2 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80306A.pdf dsPIC33FJXXXGPX06/X08/X10 Rev. A2 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70152C.pdf Flash Programming Specification]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70172A.pdf dsPIC30F to dsPIC33F Conversion Guidelines]<br />
*ICD2 Programmer<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/51331B.pdf ICD2 User's Guide] <br />
*MPLAB<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/51519B.pdf MPLAB IDE User's Guide]<br />
*C30 Compiler<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/C30_Users_Guide_51284e.pdf MPLAB C30 C Compiler User's Guide]: Contains commands for using pic30-elf-gcc <br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/16bit_Language_Tool_Libraries_51456c.pdf 16-bit Language Tools Libraries]: Contains summaries and examples of using DSP libraries, standard C libraries and device libraries<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/Asm30_Link_Util_51317e.pdf MPLAB ASM30, MPLAB LINK30 and Utilities User's Guide]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/51322d.pdf dsPIC30F Language Tools Quick Reference Card]<br />
<br />
===Code Examples===<br />
*[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1408 Microchip Example Codes for dsPic]<br />
<br />
<br />
==Programming Methods==<br />
*There are 2 programming methods: In-Circuit Serial Programming (ICSP) and Run-Time Self-Programming (RTSP)<br />
*ICSP allows the devices to be programmed after being placed in a circuit board.<br />
*RTSP allows the devices to be programmed when an embedded program is already in operation.<br />
<br />
===ICSP: External Programmer (ICD2)===<br />
*Two types of ICSP are available: '''ICSP''' and '''Enhanced ICSP'''. Both of them require setting MCLR# to V<sub>IHH</sub> (9V – 13.25V).<br />
*Standard ICSP<br />
**Use external programmer (e.g. MPLAB<sup>®</sup> ICD 2, MPLAB<sup>®</sup> PM3 or PRO MATE<sup>®</sup> II) only.<br />
**Required low-level programming to erase, program and verify the chip.<br />
**Slower, because codes are serially executed.<br />
**Program memory can be erased using ''Normal-Voltage'' (4.5 – 5.5V) or ''Low-Voltage'' (2.5V – 4.5V).<br />
<br />
*Enhanced ICSP<br />
**Use external programmer and '''Programming Executive''' (PE).<br />
**PE is stored in the on-chip memory.<br />
**PE allows faster programming.<br />
**PE can be downloaded to the chip by external programmer using the standard ICSP method.<br />
**PE contains a small command set to erase, program and verify the chip, avoiding the need of low-level programming.<br />
<br />
====Hardware Interface====<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.1 Pin Used by ICSP<br />
! Pin Label !! Function !! Pin Number<br />
|- <br />
| MCLR# || Programming Enable|| 7<br />
|-<br />
| V<sub>DD</sub> || Power Supply || 10, 26, 38, 57<br />
|-<br />
| V<sub>SS</sub> || Ground || 9, 25, 41, 56<br />
|- <br />
| PGC || Serial Clock || 17<br />
|-<br />
| PGD || Serial Data || 18<br />
|-<br />
|}<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.2 Available Programmers in the Market<br />
! Product Name<br />
! Interface with PC<br />
! Interface with Device<br />
! Price (US)<br />
! Postage (US)<br />
! Total (US)<br />
|- <br />
| [http://direct.www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en010046&part=DV164005 MPLAB<sup>®</sup> ICD 2]<br />
| USB or RS232<br />
| [http://www.microchip.com/Microchip.WWW.SecureSoftwareList/secsoftwaredownload.aspx?device=en010046&lang=en&ReturnURL=http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en010046&part=DV164005# 6-PIN RJ-12 connector]<br />
| $159.99<br />
| -<br />
| -<br />
|-<br />
| [http://www.etekronics.com/product_info.php?cPath=24&products_id=48 Full Speed USB Microchip ICD2<br> Debugger and Programmer]<br />
| USB<br />
| 6-PIN ICSP connector<br>6-PIN RJ-12 connector<br />
| $72.00<br />
| $12.00<br />
| $84.00<br />
|-<br />
| [http://www.etekronics.com/product_info.php?cPath=24&products_id=47 Mini Microchip Compatible ICD2<br> Debugger and Programmer]<br />
| RS232<br />
| 6-PIN ICSP connector<br>6-PIN RJ-12 connector<br />
| $45.00<br />
| $10.00<br />
| $55.00<br />
|-<br />
| [http://www.inexglobal.com/microcontroller.php ICDX30]<br />
| RS232<br />
| 6-pin RJ-11<br />
| $51.00<br />
| $47.46<br />
| $98.46<br />
|-<br />
| *[http://www.sure-electronics.net Clone Microchip ICD2] (Now Using)<br />
| USB<br />
| 6-pin flat cables<br />
| $30.00<br />
| $12.00<br />
| $42.00<br />
|-<br />
|}<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.3 DIY ICD 2 Programmer Circuit<br />
! Source !! Schematic !! PIC16F877A Bootloader<br />
|- <br />
| [http://membres.lycos.fr/silicium31/Electronique/PIC/FreeIcdEnglish.htm Patrick Touzet]<br />
| [http://membres.lycos.fr/silicium31/Electronique/PIC/ICD2%20V1.3.pdf Yes]<br />
| [http://membres.lycos.fr/silicium31/Electronique/PIC/ICD2_FW.zip HEX]<br />
|-<br />
| [http://www.nebadje.org/doku.php?id=neblab:icd2clone Nebadje]<br />
| [http://people.ee.ethz.ch/~jbiveron/nebadje/ICD2_DOC.pdf Yes]<br />
| [http://people.ee.ethz.ch/~jbiveron/nebadje/ICD2_FW.zip Zip]<br />
|-<br />
|}<br />
<br />
====Software Interface====<br />
*The program can be written and compiled in an Integrated Development Environment (IDE) using either Assembly or C. The complied codes are then loaded to the device through the external programmer.<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.4 Summary of IDE<br />
! Product Name !! Features !! OS !! Price (US$)<br />
|- <br />
| [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en019469&part=SW007002 MPLAB<sup>®</sup> IDE]<br />
| Assembler Only<br />
| Windows<br />
| Free<br />
|-<br />
| [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en010065&part=SW006012 MPLAB<sup>®</sup> C30]<br />
| Assembler and C-Compiler<br />
| Windows<br />
| $895.00 (Free student version<sup>1</sup>)<br />
|-<br />
| [http://linux.softpedia.com/get/Science-and-Engineering/Electronic-Design-Automation-EDA-/Piklab-8099.shtml Piklab 0.12.0]<br />
| Assembler and C-Compiler<br />
| Linux<br />
| Free<sup>2</sup><br />
|}<br />
# Full-featured for the first 60 days. After 60 days, some code optimization functions are disabled. The compiler will continue to function after 60 days, but code size may increase.<br />
# The current version supports external programmer ICD 2, but not yet tested.<br />
<br />
===RTSP: COM Port (Bootloader)===<br />
*RTSP works in normal voltage (MCLR# no need to raise to V<sub>IHH</sub>).<br />
*No literature has mentioned the incorporation of Programming Executive (PE). Presumably, since Enhanced ICSP needs to set MCLR# to V<sub>IHH</sub>, RTSP cannot use PE.<br />
*Refer to [http://www.opencircuits.com/DsPIC30F_5011_Development_Board#Bootloader_Development bootloader section].<br />
<br />
<br />
==IC Requirements==<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 3.1 IC Requirements<br />
! Part No. !! Description <br />
! Min Temp !! Max Temp !! Min Volt !! Max Volt !! Typ Cur !! Max Cur<br />
|-valign="top"<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/70116F.pdf dsPIC30F5011-30I/PT] || uP <br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 2.5V <sup>[1]</sup>|| 5.5V<br />
| 145mA || 217mA<br />
|-<br />
| [http://datasheets.maxim-ic.com/en/ds/MAX3222-MAX3241.pdf MAX3232ESE] || RS232 driver<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 3.0V || 5.5V<br />
| 0.3mA || 1.0mA<br />
|-<br />
| [http://www.national.com/ds.cgi/DS/DS3695.pdf DS3695N] || RS485 driver<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 4.75V || 5.25V<br />
| 42mA || 60mA<br />
|-<br />
| [http://focus.ti.com/lit/ds/symlink/dac6574.pdf DAC6574IDGS] || 10-bit Quad-DAC I<sup>2</sup>C<br />
| -40<sup>o</sup>C || 105<sup>o</sup>C<br />
| 2.7V || 5.5V<br />
| 0.6mA || 0.9mA<br />
|-<br />
| [http://www.semiconductors.philips.com/acrobat/datasheets/74HC_HCT14_3.pdf 74HC14D] || Quad-Schmitt Trigger<br />
| -40<sup>o</sup>C || 125<sup>o</sup>C<br />
| 2.0V || 6.0V<br />
| || 0.02mA<br />
|-<br />
| '''Overall''' || <br />
| '''-40<sup>o</sup>C''' || '''85<sup>o</sup>C'''<br />
| '''4.75V''' || '''5.25V'''<br />
| || '''<300mA <sup>[2]</sup>'''<br />
|-<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/70165E.pdf dsPIC33FJ128GP306-I/PT] || uP <br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 3.0V <sup>[1]</sup>|| 3.6V<br />
| 74mA || 250mA<br />
|-<br />
| [http://www.analog.com/UploadedFiles/Data_Sheets/ADM3485E.pdf ADM3485EARZ] || RS485 driver<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 3.0V || 3.6V<br />
| 1.1mA || 2.2mA<br />
|-<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/21203N.pdf 24LC256-I/SN] || 256kBits I2C EEPROM<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 2.5V || 5.5V<br />
| 400uA || 3mA<br />
|-<br />
| [http://www.national.com/ds.cgi/LM/LM3940.pdf LM3940IMP-3.3] || 5V-3.3V Regulator<br />
| -40<sup>o</sup>C || 125<sup>o</sup>C<br />
| 5.0V || 7.5V<br />
| 10mA || 250mA<br />
|-<br />
|}<br />
#Minimum voltage measured is 3.3V (with 2 LEDs blinking) running at 30MHz.<br />
#Measured current at 5V is 180mA (with 2 LEDs blinking only)<br />
<br />
<br />
==Development Environment==<br />
<br />
===Windows===<br />
<br />
[[Image:PIC_setup_win.JPG]]<br />
<br />
*C-Compiler, Assembler and Linker are under GNU license.<br />
**MPLAB C30 C Compiler (*.c -> *.s)<br />
**MPLAB ASM30 Assembler (*.s -> *.o)<br />
**MPLAB LINK30 Linker (*.o -> *.bin)<br />
<br />
*PA optimizer, simulator, runtime libraries, header files, include files, and linker scripts are not covered by GNU. Reference is [http://direct.forum.microchip.com/tm.aspx?m=107208 here].<br />
<br />
*Microchip has integrated ASM30, LINK30, assembly header files, linker scripts in MPLAB IDE, which is free for download.<br />
*MPLAB C30 costs US$895. A 60-day free student version is also available. After 60-days, the optimizer is automatically disabled, while other tools can still function properly. Refer to Table 2.4.<br />
<br />
*C-libraries contained in C30 includes (Refer to [http://ww1.microchip.com/downloads/en/DeviceDoc/16bit_Language_Tool_Libraries_51456c.pdf 16-Bit Language Tools Libraries] from Microchip).<br />
<br />
<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 4.1 C Libraries in MPLAB C30<br />
! Library !! Directory <br>(\\Microchip\MPLAB C30) !! Major functions<br />
|-valign="top"<br />
| DSP Library <br>(e.g. libdsp-coff.a)<br />
| \lib <br> \src\dsp <br> \support\h<br />
| Vector, Matrix, Filter, etc.<br />
|-valign="top"<br />
| 16-Bit Peripheral Libraries <br>(e.g. libp30F5011-coff.a)<br />
| \lib <br> \src\peripheral <br> \support\h<br />
| ADC12, IOPort, UART, I<sup>2</sup>C, etc.<br />
|-valign="top"<br />
| Standard C Libraries <br>(e.g. libc-coff.a, libm-coff.a, libpic-coff.a)<br />
| \lib <br> \src\libm <br> \include<br />
| stdio.h, time.h, float.h, math.h, <br />
|-valign="top"<br />
| MPLAB C30 Built-in Functions<br />
| none<br />
| _buildin_addab, _buildin_add, _buildinmpy, etc<br />
|-<br />
|}<br />
<br />
===Linux===<br />
<br />
[[Image:PIC_setup_linux.JPG]]<br />
<br />
*C Compiler, Assembler and Linker are under GNU license.<br />
**The code can be downloaded from Microchip at [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en023073 here].<br />
**Current MPLAB ASM30 Assembler: v2.04<br />
**Current MPLAB C30 Compiler: v2.04<br />
<br />
*[http://gcc.gnu.org/ml/gcc/2005-02/msg01144.html John Steele Scott] has made templates that can be readily used by Debian-based systems. <br />
*For v1.32, the necessary conversion to *.deb has been done already at [http://noel.feld.cvut.cz/dspic/ here].<br />
**Download '''pic30-1.32-debian.tar.bz2''' for Template v1.32.<br />
**Download '''pic30-binutils_1.32-1_i386.deb''' for the assember.<br />
**Download '''pic30-gcc_1.32-1_i386.deb''' for the compiler.<br />
*For v2.00<br />
**goto http://www.baycom.org/~tom/dspic/<br />
**download pic30-gcc-2.00-1.i386.rpm and pic30-binutils-2.00-1.i386.rpm<br />
**convert to deb files<br />
**install these two deb files<br />
*For v3.01, convert the Toolchain following instructions at [http://www.nabble.com/Debian-templates-for-dsPIC-build-toolchain-3.01-tf4308624.html here]<br />
**pre-install these packages: dpkg-dev, debhelper, bison, flex, sysutils, gcc-3.3, fakeroot<br />
**pack pic30-binutils into deb file<br />
**install pic30-binutils<br />
**pack pic30-gcc-3.01 into deb file<br />
**install pic30-gcc-3.01<br />
**pack pic30-support into deb file<br />
**install pic30-support<br />
*'''Important Note''': Only the compiler is free. The header files and library are owned by Microchip. <br />
**Thomas Sailer suggested to download the Student version of C30 compiler and then build the libraries without source code. A package template for Fedora system is available [http://www.baycom.org/~tom/dspic/ here].<br />
**Instructions for filling the upstream direction is available [http://forum.microchip.com/printable.aspx?m=139360 here].<br />
**Alteratively, [https://gna.org/projects/pic30-libc/ Stephan Walter] has started a project to develop C Runtime Library for dsPIC. <br />
***Current libraries in version 0.1.1 include: assert.h, cdefs.h, ctype.h, errno.h, inttypes.h, stdint.h, stdio.h, stdlib.h, string.h<br />
<br />
*Burning Program Codes to Target Board<br />
#Use 'dspicprg and dspicdmp' utilities developed by [http://homerreid.ath.cx/misc/dspicprg/ Homer Reid] to burn hex code (*.hex) to devices. See Reference [http://forum.microchip.com/tm.aspx?m=94243 here]. Through serial port only?<br />
#Use [http://piklab.sourceforge.net/ Piklab IDE]. Details on file format not known.<br />
#Use [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en019469&part=SW007002 MPLAB IDE] to burn hex code (*.hex) to devices.<br />
<br />
===Code Optimization===<br />
*Below is a comparsion between different optimization levels for the project including drivers for 2 projects.<br />
<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 4.2 Comparison between differnt optimization levels<br />
! Optimization !! Description !! Project 1<br>Code Size<br>(byte) !! Project 1<br>Data Usage<br>(byte) !! Project 2<br>Code Size<br>(byte) !! Project 2<br>Data Usage<br>(byte)<br />
|-valign="top"<br />
| O0 <br />
| No optimization<br>Fastest Compilation<br />
| 6222 (9%) || 178 (4%) || 26,037 (38%) || 710 (17%)<br />
|-valign="top"<br />
| O1 <br />
| Optimize<br> Tries to reduce code size and execution time.<br />
| 4473 (6%) || 178 (4%) || 22,290 (32%) || 710 (17%)<br />
|-valign="top"<br />
| O2 <br />
| Optimize even more<br> Performs nearly all supported optimizations <br>that do not involve a space-speed trade-off. <br>Increases both compilation time and the <br>performance of the generated code.<br />
| 4422 (6%) || 178 (4%) || 21,993 (32%) || 710 (17%)<br />
|-valign="top"<br />
| O3 <br />
| Optimize yet more. <br>O3 turns on all optimizations specified by O2 <br>and also turns on the inline-functions option.<br />
| 4485 (6%) || 178 (4%) || 22,176 (32%) || 710 (17%)<br />
|-valign="top"<br />
| Os <br />
| Optimize for size. <br>Os enables all O2 optimizations that do not <br>typically increase code size. It also performs <br>further optimizations designed to reduce code <br>size.<br />
| 4356 (6%) || 178 (4%) || 21,885 (32%) || 710 (17%)<br />
|-<br />
|}<br />
<br />
<br />
==Software Architecture==<br />
+--------+--------+--------+--------+--------+<br />
Application | Task 1 | Task 2 | Task 3 | Task 4 | Task 5 |<br />
+--------+--------+--------+--------+--------+<br />
| POSIX API |<br />
+-------------------+------------------------+<br />
OS | Coroutine | FreeRTOS Scheduler |<br />
+-------------------+------------------------+<br />
| Drivers |<br />
+------+-----+-----+--------+-------+--------+<br />
Hardware | UART | ADC | DAC | EEPROM | PWM | TIMERS | <br />
+------+-----+-----+--------+-------+--------+<br />
*Currently, operating system is based on [http://www.freertos.org/ FreeRTOS] incorporating coroutine developed by [http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html Simon Tatham]<br />
*Software Drivers are to be developed to allow users at Application Level to use the hardware (e.g. ADC, DAC, UART, EEPROM etc) through the OS.<br />
*The interface between the drivers and the OS is based on [http://www.die.net/doc/linux/man/man2/ POSIX standard] (e.g. open(), write(), read(), ioctl(), usleep() etc).<br />
*The most up-to-date development can be found at repository [http://chungyan5.no-ip.org/vc/?root=freertos_posix freertos_posix]<br />
<br />
<br />
==Programming Tips==<br />
<br />
===Memory Map for 5011===<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 6.1 Memory Location<br />
! Type !! Start Address !! End Address !! Size<br />
|-valign="top"<br />
| Flash || 0x000000 ||0x00AFFF || 44K<sup>[1]</sup><br />
|-valign="top"<br />
| +--Flash: Reset Vector || 0x000000 ||0x000003 || 4<br />
|-valign="top"<br />
| +--Flash: Interrupt Vector Table || 0x000004 ||0x00007F || 124<br />
|-valign="top"<br />
| +--Flash: Alternate Vector Table || 0x000084 ||0x0000FF || 124<br />
|-valign="top"<br />
| +--Flash: User Program || 0x000100 ||0x00AFFF || 43.7K<br />
|-valign="top"<br />
| EEPROM || 0x7FFC00 || 0x7FFFFF || 1K<sup>[2]</sup><br />
|-valign="top"<br />
| Programming Executive || 0x800000 || 0x8005BF || 1472<br />
|-valign="top"<br />
| Unit ID || 0x8005C0 || 0x8005FF || 64<br />
|-valign="top"<br />
| Config Registers || 0xF80000 || 0xF8000F || 16<br />
|-valign="top"<br />
| Device ID || 0xFF0000 || 0xFF0003 || 4<br />
|-<br />
|}<br />
[1] Each address is 16-bit wide. Every two addresses correspond to a 24-bit instruction. Each even address contains 2 valid bytes; each odd address contains 1 valid byte plus 1 phathom byte.<br><br />
[2] Each address is 8-bit wide.<br />
<br />
===Data Location===<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 6.2 Data Location<br />
! Type !! Description !! Example<br />
|-valign="top"<br />
| _XBSS(N) <sup>[1]</sup><br />
| RAM Data in X-memory, aligned at N, no initilization<br />
| int _XBSS(32) xbuf[16];<br />
|-valign="top"<br />
| _XDATA(N) <sup>[1]</sup><br />
| RAM Data in X-memory, aligned at N, with initilization<br />
| int _XDATA(32) xbuf[] = {1, 2, 3, 4, 5};<br />
|-valign="top"<br />
| _YBSS(N) <sup>[1]</sup><br />
| RAM Data in Y-memory, aligned at N, no initilization<br />
| int _YBSS(32) ybuf[16];<br />
|-valign="top"<br />
| _YDATA(N) <sup>[1]</sup><br />
| RAM Data in Y-memory, aligned at N, with initilization<br />
| int _YDATA(32) ybuf[16] = {1, 2, 3, 4, 5};<br />
|-valign="top"<br />
| __attribute__((space(const)))<br />
| Flash ROM data, constant, accessed by normal C<br>statements, but 32K max.<br />
| int i __attribute__((space(const))) = 10;<br />
|-valign="top"<br />
| __attribute__((space(prog)))<br />
| Flash ROM data, read/write by program space visibility<br>window (psv)<br />
| int i __attribute__((space(prog)));<br />
|-valign="top"<br />
| __attribute__((space(auto_psv)))<br />
| Flash ROM data, read by normal C statements, write<br>by accessing psv<br />
| int i __attribute__((space(auto_psv)));<br />
|-valign="top"<br />
| __attribute__((space(psv)))<br />
| Flash ROM data, read/write by (psv)<br />
| int i __attribute__((space(psv)));<br />
|-valign="top"<br />
| _EEDATA(N) <sup>[1]</sup><br />
| ROM Data in EEPROM, aligned at N, read/write with psv<br />
| int _EEDATA(2) table[]={0, 1, 2, 3, 5, 8};<br />
|-valign="top"<br />
| _PERSISTENT<br />
| RAM Data, data remain after reset<br />
| int _PERSISTENT var1, var2;<br />
|-valign="top"<br />
| _NEAR<br />
| RAM Data at near section<br />
| int _NEAR var1, var2;<br />
|-valign="top"<br />
| _ISR<br />
| Interrupt service rountine<br />
| void _ISR _INT0Interrupt(void);<br />
|-valign="top"<br />
| _ISRFAST<br />
| Fast interrupt service rountine<br />
| void _ISRFAST _T0Interrupt(void);<br />
|-<br />
|}<br />
#N must be a power of two, with a minimum value of 2.<br />
<br />
===Configuration Bits===<br />
----<br />
*System clock source can be provided by:<br />
#Primary oscillator (OSC1, OSC2)<br />
#Secondary oscillator (SOSCO and SOSCI) with 32kHz crystal<br />
#Internal Fast RC (FRC) oscillator at 7.37MHz (7372800Hz)<br />
#Low-Power RC (LPRC) oscillator (Watchdog Timer) at 512 kHz.<br />
*These clock sources can be incorporated with interal Phase-locked-loop (PLL) x4, x8 or x16 to yield the osciallator frequrence F<sub>OSC</sub><br />
*The system clock is divided by 4 to yield the internal instruction cycle clock, F<sub>CY</sub>=F<sub>OSC</sub>/4<br />
*FRC with PLLx16 is used to achieve F<sub>CY</sub>=29.49MHz (29491200Hz or 30MIPS)<br />
<br />
//The code (MACRO) below is to be placed at the top of program (before main)<br />
_FOSC(CSW_FSCM_OFF & FRC_PLL16);<br />
_FWDT(WDT_OFF); //Turn off Watchdog Timer<br />
_FBORPOR(PBOR_ON & BORV_27 & MCLR_DIS & PWRT_16);<br />
_FGS(CODE_PROT_OFF); //Disable Code Protection<br />
<br />
===Timer===<br />
<br />
----<br />
*Each timer is 16-bit (i.e. counting from 0 to 65535).<br />
*Timer 2 and 3 can be incorporated together to form a 32-bit timer.<br />
*Prescale is the ratio between timer counts and system clock counts. Prescales of 1:1, 1:8, 1:64 and 1:256 are available.<br />
*Timers may be used to implement free time clock or mesaure time.<br />
<br />
====Free Time Clock====<br />
*Let required time for ticking be PERIOD.<br />
*Number of instruction cycles during PERIOD = PERIOD*F<sub>CY</sub> cycles<br />
*Using a prescale of 1:x, the timer period count register = # of cycles/x<br />
*e.g. PERIOD = 10ms; # of cycles = 10ms*30MHz = 300000 cylces; Using 1:64 Prescale, register setting = 300000/64 = 4688<br />
void time_init(void){<br />
TMR1 = 0; // Clear register<br />
PR1 = 4688; // Set period<br />
//============================================================<br />
_T1IF = 0; // Clear interrupt flag<br />
_T1IE = 1; // Enable interrupts<br />
//============================================================<br />
T1CONbits.TCS = 0; // Use internal clock source<br />
T1CONbits.TCKPS = 2; // Prescale Select 1:64<br />
T1CONbits.TON = 1; // Start the timer <br />
}<br />
//********************************************************************<br />
void _ISRFAST _T1Interrupt(void){<br />
_T1IF = 0; // Clear interrupt flag<br />
//Place user code here<br />
}<br />
<br />
====Time Measurement====<br />
*To measure the time taken for action(), use the code below:<br />
unsigned int measure_time(void){ <br />
PR3 = 0xFFFF; // Set counter to maximum<br />
_T3IF = 0; // Clear interrupt flag<br />
_T3IE = 0; // Disable interrupt<br />
T3CONbits.TON = 1; // Start the timer, TMR3 count up<br />
TMR3 = 0; //Clear TMR3 to start count up<br />
//====================================================<br />
//Add code here to wait for something to happen<br />
action();<br />
//====================================================<br />
T3CONbits.TON = 0; //Stop the timer<br />
//====================================================<br />
return (unsigned int) TMR3/FCY; //TMR/FCY yields the actual time<br />
}<br />
<br />
===Interrupt===<br />
<br />
----<br />
*Registers are involved in Interrupts includes: <br />
#Interrupt Flag Status (IFS0-IFS2) registers<br />
#Interrupt Enable Control (IEC0-IEC2) registers<br />
#Interrupt Priority Control (IPC0-IPC10) registers<br />
#Interrupt Priority Level (IPL) register<br />
#Global Interrupt Control (INTCON1, INTCON2) registers<br />
#Interrupt vector (INTTREG) register<br />
*User may assign priority level 0-7 to a specific interrupt using IPC. Setting priority to 0 disable a specific interrupt. Level 7 interrupt has the highest priority.<br />
*Current priority level is stored in bit<7:5> of Status Register (SR). Setting Interrupt Priority Level (IPL) to 7 disables all interrupts (except traps). <br />
*sti() and cli() can be defined to enable and disable global interrupts for time critical functions:<br />
#define IPL ( 0x00e0 )<br />
#define cli() SR |= IPL //Set IPL to 7<br />
#define sti() SR &= ~IPL //Set IPL to 0<br />
//============================================================<br />
char adc_ioctl(unsigned char request, unsigned char* argp){<br />
//...<br />
cli(); //Disable global interrupt<br />
for(;ch<=argp[0];ch++)<br />
adc_add_ch(argp[ch]); //Add adc channels<br />
sti(); //Enable global interrupt<br />
//...<br />
return 0;<br />
}<br />
*dsPic30F has an [http://ww1.microchip.com/downloads/en/DeviceDoc/80223D.pdf errate note] on the Interrupt Controller. When Nested Interrupt is turned on (NSTDIS=0 by default), a high priority interrupt negating a low priority interrupt may result in an Address Error.<br />
*To work around the problem, it is suggested by Microchip to use the following MACRO to protect:<br />
# the clearing of Interrput Flag<br />
# the disabling of Interrupt Enable<br />
# the lowering of Interrupt Priority <br />
# the modification of IPL in Status Register to 1-6<br />
#define DISI_PROTECT(X) { \<br />
__asm__ volatile ("DISI #0x1FFF");\<br />
X; \<br />
DISICNT = 0; \<br />
}<br />
*For example,<br />
void _ISR _T1Interrupt( void )<br />
{<br />
DISI_PROTECT(IFS0bits.T1IF = 0);<br />
//do something here...<br />
}<br />
<br />
===UART===<br />
<br />
----<br />
*5011 provides two UART channels UxART, for x=1, 2.<br />
*UxMODE, UxSTA, UxBRG are registers used to set the mode, indicate the status, and set the baud rate respectively.<br />
*For UART communications compatiable with RS232 standard, an external driver (e.g. MAX3232ESE) is needed.<br />
*For UART communications compatiable with RS485 standard, an external driver (e.g. DS3695N) is needed.<br />
====Auto baud rate detection====<br />
*The method is provided by [http://www.opencircuits.com/DsPIC30F_5011_Development_Board ingenia bootloader].<br />
*The PC sends a ASCII character 'U' (0x55) to the target board.<br />
*On the first rising edge of the start bit, the target board starts the timer.<br />
*At the fifth rising edge, the timer is stopped, let the count number be ''t_count''. <br />
**The measured period corresponds to 8 bits transmitted at a baud rate ''uxbrg''.<br />
_ _ _ _ _ _<br />
_|S|_|1|_|1|_|1|_|1|_|S|_ (S = Start Bit)<br />
<---------------><br />
Measured Time<br />
*The relationship between ''uxbrg'' and ''TMR'' is<br />
Measured Time (in seconds) = t_count/F<sub>cy</sub><br />
uxbrg = 1/(Measured Time/8)<br />
= 8*F<sub>cy</sub>/t_count<br />
*Since UxBRG is computed by:<br />
UxBRG = (F<sub>cy</sub>/(16*Baudrate)) -1<br />
= (F<sub>cy</sub>/(16*8*F<sub>cy</sub>/t_count)) -1<br />
= t_count/128 -1<br />
*The following is the code for auto baud rate detection for U2ART:<br />
unsigned int uart2_autobaud(void){<br />
U2MODEbits.ABAUD = 1; //Enable Autobaud detect from U2RX (from IC2 if 0)<br />
U2MODEbits.UARTEN = 1; //U2ART enable<br />
//Timer 3 Config==========================================================<br />
PR3 = 0xFFFF; // Set counter to maximum<br />
_T3IF = 0; // Clear interrupt flag<br />
_T3IE = 0; // Disable interrupt<br />
T3CONbits.TON = 1; // Start the timer, TMR3 count up<br />
//Input Capture Config====================================================<br />
IC2CONbits.ICM = 3; //Detect rising <br />
_IC2IF = 0; //Clear interrupt flag<br />
_IC2IE = 0; //Disable interrupt<br />
//Start Auto baud detection===============================================<br />
unsigned int i=0;<br />
cli(); //Disable Global Interrupt<br />
while(!_IC2IF); //1st rising edge detected<br />
TMR3 = 0; //Clear TMR3 to start count up<br />
_IC2IF = 0; //Clear interrupt flag<br />
while(!_IC2IF); //2nd rising edge detected<br />
_IC2IF = 0; //Clear interrupt flag<br />
while(!_IC2IF); //3rd rising edge detected<br />
_IC2IF = 0; //Clear interrupt flag<br />
while(!_IC2IF); //4th rising edge detected<br />
_IC2IF = 0; //Clear interrupt flag<br />
while(!_IC2IF); //5th rising edge detected<br />
_IC2IF = 0; //Clear interrupt flag<br />
T3CONbits.TON = 0; //Stop the timer<br />
sti(); //Enable Global Interrupt<br />
//Compute value for BRG register==========================================<br />
unsigned int time;<br />
time = ((TMR3+0x40)>>7)-1; //+0x40 for rounding<br />
//========================================================================<br />
return time;<br />
}<br />
*For 30MIP, tested speeds of transmission include 9600bps, 19200bps, 28800bps, 38400bps and 57600bps.<br />
====open()====<br />
*The following structures and variables are used as circular buffers for transmit and receive.<br />
struct UART_Rx{<br />
unsigned char wr;<br />
unsigned char rd;<br />
};<br />
struct UART_Tx{<br />
unsigned char wr; <br />
unsigned char rd;<br />
unsigned char tx_complete_flag;<br />
};<br />
struct UART_Rx uart_rx;<br />
struct UART_Tx uart_tx;<br />
unsigned char uart_rx_buf[MAX_UART_RX_BUF];<br />
unsigned char uart_tx_buf[MAX_UART_TX_BUF];<br />
<br />
char uart_open()<br />
{<br />
uart_rx.wr = 0;<br />
uart_rx.rd = 0;<br />
uart_tx.wr = 0;<br />
uart_tx.rd = 0;<br />
uart_tx.tx_complete_flag = 1;<br />
uart2_init();<br />
return 0;<br />
}<br />
<br />
void uart2_init(void){<br />
unsigned int u2brg = 97; <br />
#if(AUTO_BAUD_DECT>0)<br />
u2brg = uart2_autobaud();<br />
#endif<br />
U2BRG = u2brg; <br />
//=================================================================<br />
// Disable U2ART<br />
U2MODEbits.UARTEN = 0; //Disable U2ART module<br />
//=================================================================<br />
// Configure Interrupt Priority<br />
_U2RXIF = 0; //Clear Rx interrupt flags<br />
_U2TXIF = 0; //Clear Tx interrupt flags<br />
_U2RXIE = 1; //Receive interrupt: 0 disable, 1 enable <br />
_U2TXIE = 1; //Transmit interrupt: 0 disable, 1 enable<br />
//=================================================================<br />
// Configure Mode<br />
// +--Default: 8N1, no loopback, no wake in sleep mode, continue in idle mode<br />
// +--Diable autobaud detect<br />
// +--Enable U2ART module<br />
U2MODEbits.ABAUD = 0; //Disable Autobaud detect from U2RX <br />
U2MODEbits.UARTEN = 1; //U2ART enable<br />
//=================================================================<br />
// Configure Status<br />
// +--Default: TxInt when a char is transmitted, no break char<br />
// +--Default: RxInt when a char is received, no address detect, clear overflow<br />
// +--Enable Transmit<br />
U2STAbits.UTXEN = 1; //Tx enable<br />
}<br />
<br />
====write()====<br />
*This function writes a series of bytes to the circular buffer and start transmission.<br />
int uart_write(unsigned char *buf, int count)<br />
{<br />
//If transimt has not completed, return busy<br />
if(uart_tx.tx_complete_flag == 0){<br />
return -1; <br />
}<br />
else{<br />
uart_tx.tx_complete_flag = 0;<br />
}<br />
int next_data_pos;<br />
int byte = 0;<br />
for (; byte<count; byte++) {<br />
next_data_pos = pre_wr_cir254buf( (unsigned char)uart_tx.wr, <br />
(unsigned char)uart_tx.rd, <br />
MAX_UART_TX_BUF); <br />
if (next_data_pos!=255) {<br />
//Valid data is available<br />
uart_tx_buf[uart_tx.wr] = (unsigned char) buf[byte]; //copy the char to tx_buf<br />
uart_tx.wr = next_data_pos; //increment the ptr<br />
} else break;<br />
}<br />
//Raise Interrupt flag to initiate transmission<br />
_U2TXIF = 1; //Start interrupt<br />
return byte; <br />
}<br />
*The interrupt routine reads from the circular buffer and send the data. The uart is opened such that the module will generate an TX Interrupt when it a byte is sent.<br />
void _ISR _U2TXInterrupt(void){<br />
DISI_PROTECT(_U2TXIF = 0); //Clear Interrupt Flag<br />
unsigned char next_data_pos;<br />
next_data_pos = pre_rd_cir254buf( (unsigned char)uart_tx.wr,<br />
(unsigned char)uart_tx.rd, <br />
MAX_UART_TX_BUF);<br />
if (next_data_pos!= 255) {<br />
//Valid Data is available to transmit<br />
U2TXREG = (uart_tx_buf[(unsigned char)uart_tx.rd] & 0xFF); //send next byte...<br />
uart_tx.rd = (unsigned char) next_data_pos; //update rd pointer<br />
} else {<br />
//Transimission has completed<br />
uart_tx.tx_complete_flag = 1; // change to empty of tx<br />
}<br />
}<br />
<br />
====read()====<br />
*The interrupt routine writes to the circular buffer when space is available.<br />
void _ISR _U2RXInterrupt(void){<br />
unsigned char next_data_pos;<br />
if ( U2STAbits.URXDA ){<br />
next_data_pos = pre_wr_cir254buf( uart_rx.wr, uart_rx.rd, MAX_UART_RX_BUF);<br />
if (next_data_pos!=255) {<br />
//If buffer is not full<br />
uart_rx_buf[uart_rx.wr] = (unsigned char) U2RXREG; //Read the data from buffer<br />
uart_rx.wr = next_data_pos;<br />
} <br />
else{<br />
//When buffer is full, still remove data from register, butthe incoming data is lost<br />
next_data_pos = (unsigned char) U2RXREG; //Read the data from buffer<br />
} <br />
}<br />
DISI_PROTECT(_U2RXIF = 0); //Clear the flag<br />
}<br />
*This function reads one byte from the circular buffer.<br />
int uart_read(unsigned char *buf)<br />
{<br />
int next_data_pos;<br />
next_data_pos = pre_rd_cir254buf( uart_rx.wr, uart_rx.rd, MAX_UART_RX_BUF);<br />
//Copy 1 byte when data is available<br />
if (next_data_pos!=255) <br />
{<br />
*buf = uart_rx_buf[uart_rx.rd]; //copy the stored data to buf<br />
uart_rx.rd = next_data_pos; //update the ptr<br />
return 1;<br />
}<br />
//No data can be copied<br />
else<br />
{<br />
return 0;<br />
} <br />
}<br />
<br />
===I<sup>2</sup>C===<br />
<br />
----<br />
*Two lines are devoted for the serial communication. SCL for clock, SDA for data.<br />
*Standard communication speed includes<br />
#Standard speed mode: 100kHz<br />
#Fast speed mode: 400kHz<br />
#High speed mode: 3.4MHz<br />
*dsPIC30f5011 supports standard and fast speed modes. The maximum speed attainable is 1MHz.<br />
*Pull-up resistors are required for both SCL and SDA. Minimum pull-up resistance is given by:<br />
Pull-up resistor (min) = (V<sub>dd</sub>-0.4)/0.003 ...... [See section 21.8 in Family reference manual]<br />
*2.2Kohm is typical for standard speed mode.<br />
*After initiating a start/stop/restart bit, add a small delay (e.g. no operation) before polling the corresponding control bit (hardware controlled).<br />
*After sending a byte and receiving an acknowledgement from the slave device, ensure to change to idle state.<br />
<br />
====open()====<br />
*The following structure is used to record whether special bits are needed to be sent.<br />
typedef union{<br />
unsigned char val;<br />
struct{<br />
unsigned START:1; //start<br />
unsigned RESTART:1; //restart<br />
unsigned STOP:1; //stop<br />
unsigned NACK:1; //not acknowledgment<br />
unsigned :1;<br />
unsigned :1;<br />
unsigned :1;<br />
unsigned :1; <br />
}bits;<br />
} I2C_STATUS;<br />
static I2C_STATUS i2c_status; <br />
<br />
*Initializing I<sup>2</sup>C with default speed I2C_BRG without interrupts.<br />
void i2c_open(void)<br />
{<br />
//Open i2c if not already opened<br />
if(I2CCONbits.I2CEN == 0)<br />
{<br />
_SI2CIF = 0; //Clear Slave interrupt<br />
_MI2CIF = 0; //Clear Master interrupt<br />
_SI2CIE = 0; //Disable Slave interrupt<br />
_MI2CIE = 0; //Disable Master interrupt<br />
I2CBRG = I2C_BRG;<br />
I2CCONbits.I2CEN = 1; //Enable I2C module <br />
i2cIdle(); //I2C bus at idle state, awaiting transimission<br />
i2c_status.val = 0; //clear status flags<br />
}<br />
}<br />
<br />
====ioctl()====<br />
*Use this function before read/write to append special bits before or after the data byte.<br />
char i2c_ioctl(unsigned char request, unsigned char* argp)<br />
{<br />
switch(request){<br />
case I2C_SET_STATUS:<br />
i2c_status.val = *argp;<br />
break;<br />
default:<br />
return -1; //request code not recognised <br />
}<br />
return 0;<br />
}<br />
<br />
====write()====<br />
*This function sends an 8-bit data using the I2C protocol.<br />
Mst/Slv _______ M ____M___ S M ________ <br />
SDA (Data) |S| data |A|S|<br />
|T| |C|T|<br />
|A|XXXXXXXX|K|P|<br />
*Use ioctl() to select whether a start/restart/stop bit is required.<br />
*If slave does not respond after ACK_TIMEOUT, the transmission is considered unsucessful.<br />
int i2c_write(unsigned char *buf)<br />
{<br />
unsigned int count = 0;<br />
if(i2c_status.bits.START)<br />
{<br />
I2CCONbits.SEN = 1; <br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.SEN); //Wait till Start sequence is completed<br />
}<br />
else if(i2c_status.bits.RESTART)<br />
{<br />
I2CCONbits.RSEN = 1; <br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.RSEN); //Wait till Start sequence is completed<br />
}<br />
I2CTRN = *buf; //Transmit register<br />
while(I2CSTATbits.TBF); //Wait for transmit buffer to empty<br />
while(I2CSTATbits.ACKSTAT){<br />
if(++count > ACK_TIMEOUT){<br />
//Slave did not acknowledge, byte did not transmit sucessfully, <br />
//send stop bit to reset i2c<br />
I2CCONbits.PEN = 1;<br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.PEN); //Wait till stop sequence is completed<br />
i2cIdle();<br />
return 0;<br />
}<br />
}<br />
i2cIdle();<br />
if(i2c_status.bits.STOP)<br />
{<br />
I2CCONbits.PEN = 1;<br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.PEN); //Wait till stop sequence is completed<br />
i2cIdle();<br />
}<br />
i2c_status.val = 0; //Clear status<br />
return 1;<br />
}<br />
<br />
====read()====<br />
*This function reads 1 byte from slave using the I2C protocol.<br />
Mst/Slv ____ ___S____ M M _____ <br />
SDA (Data) | data |A|S|<br />
| |C|T|<br />
|XXXXXXXX|K|P|<br />
*Use ioctl() to select whether an ACK/NACK and/or STOP bit is needed to be sent.<br />
int i2c_read(unsigned char *buf)<br />
{<br />
I2CCONbits.RCEN = 1; //Enable Receive<br />
while(I2CCONbits.RCEN);<br />
I2CSTATbits.I2COV = 0; //Clear receive overflow<br />
*buf = (unsigned char) I2CRCV; //Access the receive buffer<br />
I2CCONbits.ACKDT = (i2c_status.bits.NACK)? 1 : 0;<br />
I2CCONbits.ACKEN = 1; //Send Acknowledgement/Not Acknowledgement<br />
i2cIdle(); //I2C bus at idle state, awaiting transimission<br />
if(i2c_status.bits.STOP)<br />
{<br />
I2CCONbits.PEN = 1;<br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.PEN); //Wait till stop sequence is completed<br />
i2cIdle();<br />
}<br />
i2c_status.val = 0; //Clear status<br />
return 1;<br />
}<br />
<br />
====Example====<br />
Mst/Slv _______ M ___M___ M S ____M___ S M ___M___ M S ___S____ M ___S____ M M _____ <br />
SDA (Data) |S| | |A| |A|R| | |A| |A| |N|S|<br />
|T|address|W|C|channelA|C|E|address|R|C| Data H |C| Data L |A|T|<br />
|A|1001111|0|K|00010010|K|S|1001111|1|K|10101010|K|10XXXXXX|K|P|<br />
<br />
/*<br />
* Send start bit, slave address (Write Mode)<br />
*/ <br />
status = I2C_START;<br />
i2c_ioctl(I2C_SET_STATUS, &status);<br />
data = (unsigned char) I2C_SLAVE_ADDR;<br />
i2c_write(&data);<br />
/*<br />
* Send control byte: Channel select<br />
*/<br />
data = (unsigned char) ctrl_byte;<br />
i2c_write(&data);<br />
/*<br />
* Send restart bit, slave address (Read Mode)<br />
*/<br />
status = I2C_RESTART;<br />
i2c_ioctl(I2C_SET_STATUS, &status);<br />
data = (unsigned char) (I2C_SLAVE_ADDR|0x01);<br />
i2c_write(&data);<br />
/*<br />
* Receive High Byte with Acknowledgment<br />
*/<br />
i2c_read(&data);<br />
usr_data.high = (unsigned char) data;<br />
/*<br />
* Receive Low Byte with Not Acknowledgment and stop bit<br />
*/ <br />
status = I2C_NACK | I2C_STOP;<br />
i2c_ioctl(I2C_SET_STATUS, &status);<br />
i2c_read(&data);<br />
usr_data.low = (unsigned char) data;<br />
<br />
===ADC===<br />
<br />
----<br />
*12-bit ADC: (Max 16 Channels)<br />
*Allow a maximum of 2 sets of analog input multiplexer configurations, MUX A and MUX B (Normally use one only).<br />
*A maximum of 200kps of sampling rate when using auto sampling mode.<br />
====open()====<br />
*The following variables are required.<br />
unsigned int adc_buf[ADC_MAX_CH]; //Store most updated data<br />
volatile unsigned int* ADC16Ptr = &ADCBUF0; //Pointer to ADC register buffer, <br />
unsigned char adc_ch_select = 0; //Pointer to channel to be read from<br />
unsigned char adc_data_ready = 0; //Indicate if RAM data is ready for output<br />
*Configuration is highlighted below.<br />
**Interrupt: The ADC module will be set to interrupt when the specified channels are updated.<br />
**I/O: Set the corresponding TRISBX bits (digit i/o config) to input (i.e. = 1), and set corresponding bits in ADPCFG (analog config) to zero.<br />
**Scanning Mode: Scan mode is used. In this mode, the Sample and Hold (S/H) is switched between the channels specified by ADCSSL (Scan select register).<br />
**Reference Voltage for S/H: Only MUX A is used. By default, the negative reference voltage of the S/H is connected to V<sub>REF-</sub>.<br />
**Settings for ADC Operation: For 200kbps operation, the voltage references for the ADC voltage are connected to V<sub>REF+</sub> and V<sub>REF-</sub>. Scan input is enabled, and the module will generate an interrupt when all selected channels have been scanned.<br />
**Sampling Rate: T<sub>AD</sub> refers to the time unit for the ADC clock. To configure the ADC module at 200kbps, the minimum sampling time of 1T<sub>AD</sub> = 334ns is required. ADCS<5:0> in ADCON3 register is used to set the time, which is given by:<br />
ADCS<5:0> = 2(T<sub>AD</sub>/T<sub>CY</sub>)-1 <br />
= 2(334e-9/33.34e-9)-1 <br />
= 19<br />
<br />
char adc_open(int flags)<br />
{<br />
// Configure interrupt<br />
_ADIF = 0; //clear ADC interrupt flag<br />
_ADIE = 1; //enable adc interrupt<br />
// Configure analog i/o <br />
_TRISB0 = 1;<br />
_TRISB1 = 1; <br />
ADPCFG = 0xFFFC; //Enable AN0 (Vref+) and AN1 (Vref-)<br />
// Configure scan input channels <br />
ADCSSL = 0x0003; //0 => Skip, 1 => Scan<br />
// Configure CH0 Sample and Hold for 200kbps<br />
// +-- Use MUX A only<br />
// +-- Set CH0 S/H -ve to VRef-<br />
ADCHSbits.CH0NA = 0;<br />
// ADCCON3:<br />
// +--Auto Sample Time = 1TAD<br />
// +--A/D Conversion Clock Source = system clock<br />
// +--A/D Conversion Clock Select ADCS<5:0>= 2(TAD/TCY)-1<br />
// 200kbps(Sampling frequency)<br />
ADCON3bits.SAMC = ADC_ACQ_TIME; //1TAD for sampling time<br />
ADCON3bits.ADRC = 0; //Use system clock<br />
ADCON3bits.ADCS = ADC_ADCS; //each conversion requires 14TAD<br />
// ADCCON2:<br />
// +--Default: Use MUX A, No splitting of Buffer<br />
// +--Voltage Reference Configuration Vref+ and Vref-<br />
// +--Scan Input Selections<br />
// +--5 samples between interrupt<br />
ADCON2bits.VCFG = 3; //External Vref+, Vref-<br />
ADCON2bits.CSCNA = 1; //Scan input<br />
ADCON2bits.SMPI = 1; //take 2 samples (one sample per channel) per interrupt<br />
// ADCCON1:<br />
// +--Default: continue in idle mode, integer format<br />
// +--Enable ADC, Conversion Trigger Source Auto, Auto sampling on<br />
ADCON1bits.FORM = 0; //[0:integer]; [2 fractional]; [3 siged fractional]<br />
ADCON1bits.SSRC = 7; //auto covert, using internal clock source<br />
ADCON1bits.ASAM = 1; //auto setting of SAMP bit<br />
ADCON1bits.ADON = 1; //Turn on module<br />
return 0;<br />
}<br />
<br />
====read()====<br />
*16 registers (ADCBUF0 -ADCBUF15) are dedicated to store the ADC data between interrupts. However, the data in ADCBUFx does not necessarily correspond to the data taken for channel x. Since the lowest register will always be filled first, when some of the channels are not scanned (i.e. skipped), care must be taken. The following code checks the ADCSSL register for the current scanning channels and moves the data to the corresponding position in *adc_buf.<br />
void _ISR _ADCInterrupt(void){<br />
unsigned int channel = 0;<br />
unsigned int buffer = 0;<br />
for (; channel<ADC_MAX_CH; channel++)<br />
{<br />
if(select(channel)) //Check if channel has been selected<br />
{<br />
adc_buf[channel] = ADC16Ptr[buffer]; //Copy data to adc_buf<br />
buffer++;<br />
}<br />
}<br />
adc_data_ready = 1;<br />
DISI_PROTECT(_ADIF = 0); //Clear adc interrupt<br />
}<br />
<br />
static unsigned char select(unsigned char ch)<br />
{<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
if(ADCSSL & mask)<br />
return 1;<br />
return 0;<br />
}<br />
*User can read from the buffer at anytime to get the most updated analog values.<br />
int adc_read(unsigned int* buf, int count)<br />
{<br />
if(adc_data_ready == 1)<br />
{<br />
int num_channel = count/2; //number of channels to read<br />
unsigned char channel = adc_ch_select; //index for adc_buf<br />
int i = 0; //index for buf<br />
while(i<num_channel && channel<ADC_MAX_CH)<br />
{ <br />
//Loop only for specified number of channel or all channels <br />
buf[i++] = adc_buf[channel++]; //use data in local buffer<br />
while(select(channel)==0)<br />
{ //increment to next valid channel<br />
channel++; <br />
if(channel >= ADC_MAX_CH) break;<br />
}<br />
}<br />
return 2*i;<br />
}<br />
return -1;<br />
}<br />
<br />
====ioctl()====<br />
*This function is used to add or remove channels from the ADC scanning process.<br />
char adc_ioctl(unsigned char request, unsigned char* argp)<br />
{<br />
switch(request)<br />
{<br />
case ADC_ADD_CH:<br />
//ADD channels to current set==========================<br />
cli(); //Disable global interrupt<br />
if(select(argp[0]) == 0){ //If channel not in scan list<br />
adcAdd(argp[0]); //Add individual channel to scan list<br />
adc_data_ready = 0; //First data not ready yet, until interrupt occurs<br />
}<br />
adc_ch_select = argp[0]; //Select current channel for reading<br />
sti(); //Enable global interrupt<br />
break;<br />
case ADC_RM_CH:<br />
//REMOVE channels from current set==========================<br />
cli(); //Disable global interrupt<br />
if(select(argp[0])){ //If channel in scan list <br />
adcRm(argp[0]); //Remove individual channel<br />
adc_ch_select = 0; //Reset to AN0<br />
}<br />
sti(); //Enable global interrupt<br />
break;<br />
default:<br />
return -1; //request code not recognised <br />
}<br />
return 0;<br />
}<br />
*Channels may be added or removed by changing _TRISBX, ADPCFG, ADCSSL and ADCON2bits.SMPI.<br />
void adc_add_ch(unsigned char ch){<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
TRISB = TRISB | mask;<br />
ADCSSL = ADCSSL | mask; <br />
ADPCFG = ~ADCSSL;<br />
ADCON2bits.SMPI++; //take one more sample per interrupt<br />
}<br />
<br />
void adc_rm_ch(unsigned char ch){<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
ADPCFG = ADPCFG | mask;<br />
ADCSSL = ~ADPCFG;<br />
ADCON2bits.SMPI--; //take one less sample per interrupt<br />
}<br />
<br />
===EEPROM===<br />
<br />
----<br />
*5011 has 1024 bytes of EEPROM, readable and writable under normal voltage (5V).<br />
*To use, declare:<br />
unsigned char _EEDATA(2) eeData[1024]={ 0x00, 0x00, 0x00, 0x00, .... }<br />
unsigned int byte_pointer = 0;<br />
====lseek()====<br />
*This function moves the pointer to the desired position before a reading/writing operation is performed.<br />
int eeprom_lseek(int offset, unsigned char whence){<br />
byte_pointer = offset;<br />
return byte_pointer;<br />
}<br />
====read()====<br />
*This function read ''count'' bytes from the eeprom.<br />
int eeprom_read(unsigned char* buf, int count){<br />
int i=0;<br />
for(; i<count && byte_pointer < 1024; i++){<br />
readEEByte( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + byte_pointer, <br />
&buf[i]);<br />
byte_pointer++; //Update global pointer<br />
}<br />
return i; //read i bytes successful <br />
}<br />
*readEEByte() is implemented in assembly code as follows:<br />
.global _readEEByte<br />
_readEEByte:<br />
push TBLPAG ;w0 = base of eeData<br />
mov w0, TBLPAG ;w1 = offset for eeData in byte<br />
tblrdl.b [w1], [w2] ;w2 = pointer to user buffer<br />
pop TBLPAG<br />
return<br />
<br />
====write()====<br />
*This function write ''count'' bytes to eeprom.<br />
int eeprom_write(unsigned char* buf, int count){<br />
char isOddAddr = byte_pointer%2; //current address is odd<br />
char isOddByte = count%2; //number of bytes to write is odd<br />
//=================================================================<br />
unsigned int word_offset = byte_pointer>>1; //div by 2 and round down<br />
int max_write;<br />
max_write = (isOddAddr == 0 && isOddByte == 0) ? (count>>1) : (count>>1)+1;<br />
//=================================================================<br />
unsigned int word_data; //Store word to be written<br />
int byte_wr = 0; //number of bytes written, i.e buffer pointer<br />
int i = 0;<br />
//=================================================================<br />
for(; i<max_write && word_offset<512; i++, word_offset++){<br />
if(i==0 && isOddAddr){<br />
//First byte not used<br />
//============================================save first byte<br />
readEEByte( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + byte_pointer - 1,<br />
&word_data);<br />
//===========================================================<br />
word_data = ((unsigned int)buf[0] << 8) + (0xFF & word_data);<br />
byte_wr++; //Update buffer pointer<br />
byte_pointer++; //Update global pointer<br />
} else if(i==max_write-1 && ((isOddAddr && sOddByte==0)||(isOddAddr==0 && isOddByte))){<br />
//Last byte not used<br />
//=============================================save last byte<br />
readEEByte( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + byte_pointer + 1,<br />
&word_data);<br />
//============================================================<br />
word_data = (word_data << 8) + buf[byte_wr];<br />
byte_wr++; //Update buffer pointer<br />
byte_pointer++; //Update global pointer<br />
} else{<br />
//Both bytes valid<br />
word_data = ((unsigned int)buf[byte_wr+1] << 8) + buf[byte_wr];<br />
byte_wr+=2; //Update buffer pointer<br />
byte_pointer+=2; //Update global pointer<br />
}<br />
//==================================================================<br />
eraseEEWord( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + 2*word_offset);<br />
writeEEWord( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + 2*word_offset,<br />
&word_data);<br />
//==================================================================<br />
}<br />
return byte_wr; //No. of byte written<br />
}<br />
*eraseEEWord and writeEEWord are implemented in assembly.<br />
.global _eraseEEWord<br />
_eraseEEWord:<br />
push TBLPAG <br />
mov w0, NVMADRU ;w0 = base of eeData<br />
mov w1, NVMADR ;w1 = offset for eeData in word<br />
mov #0x4044, w0 <br />
mov w0, NVMCON ;Set to erase operation<br />
push SR ;Disable global interrupts<br />
mov #0x00E0, w0<br />
ior SR<br />
mov #0x55, w0 ;Write the KEY sequence<br />
mov w0, NVMKEY<br />
mov #0xAA, w0 <br />
mov w0, NVMKEY<br />
bset NVMCON, #15 ;Start the erase cycle, bit 15 = WR<br />
nop<br />
nop<br />
L1: btsc NVMCON, #15 ;while(NVMCONbits.WR)<br />
bra L1<br />
clr w0<br />
pop SR ;Enable global interrupts<br />
pop TBLPAG<br />
return<br />
<br />
.global _writeEEWord<br />
_writeEEWord:<br />
push TBLPAG ;w0 = base of eeData<br />
mov w0, TBLPAG ;w1 = offset for eeData in byte<br />
tblwtl [w2], [w1] ;w2 = pointer to user buffer<br />
mov #0x4004, w0 ;Set to write operation<br />
MOV w0, NVMCON<br />
push SR ;Disable global interrupts<br />
mov #0x00E0, w0<br />
ior SR<br />
mov #0x55, w0 ;Write the KEY sequence<br />
mov w0, NVMKEY<br />
mov #0xAA, w0 <br />
mov w0, NVMKEY<br />
bset NVMCON, #15 ;Start the erase cycle, bit 15 = WR<br />
nop<br />
nop<br />
L2: btsc NVMCON, #15 ;while(NVMCONbits.WR)<br />
bra L2<br />
clr w0<br />
pop SR ;Enable global interrupts<br />
pop TBLPAG<br />
return<br />
<br />
===Simple PWM (Output Compare Module)===<br />
<br />
----<br />
<br />
*The PWM module consists of 8 channels using the output compare module of dsPic.<br />
*These channels are locate at pin 46 (OC1), 49 (OC2), 50 (OC3), 51 (OC4), 52 (OC5), 53 (OC6), 54 (OC7), 55 (OC8). These pins are shared with port D.<br />
*The range of PWM freqeuencies obtainable is 2Hz to 15MHz (See Figure 6.3). Suggested range of operation is 2Hz to 120kHz. The relationship between resolution ''r'' and PWM frequency ''f''<sub>PWM</sub> is given by:<br />
f<sub>PWM</sub> = f<sub>CY</sub>/(Prescale*10<sup>rlog(2)</sup>)<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 6.3 Relationship of Resolution and PWM Frequency<br />
! Resolution (bit) !! Prescale=1 !! Prescale=8 !! Prescale=64 !! Prescale=256<br />
|- <br />
|1||15,000,000 ||1,875,000 ||234,375||58,594 <br />
|- <br />
|2||7,500,000 ||937,500 ||117,188 ||29,297 <br />
|- <br />
|3||3,750,000 ||468,750 ||58,594 ||14,648 <br />
|- <br />
|4||1,875,000 ||234,375 ||29,297 ||7,324 <br />
|- <br />
|5||937,500 ||117,188 ||14,648 ||3,662 <br />
|- <br />
|6||468,750 ||58,594 ||7,324 ||1,831 <br />
|- <br />
|7||234,375 ||29,297 ||3,662 ||916 <br />
|- <br />
|8||117,188 ||14,648 ||1,831||458 <br />
|- <br />
|9||58,594 ||7,324 ||916 ||229 <br />
|- <br />
|10||29,297 ||3,662 ||458 ||114 <br />
|- <br />
|11||14,648 ||1,831 ||229||57 <br />
|- <br />
|12||7,324 ||916 ||114 ||29 <br />
|- <br />
|13||3,662 ||458 ||57 ||14 <br />
|- <br />
|14||1,831 ||229 ||29 ||7 <br />
|- <br />
|15||916 ||114 ||14 ||4 <br />
|- <br />
|16||458 ||57 ||7 ||2 <br />
|-<br />
|}<br />
<br />
====open()====<br />
*A timer (either Timer 2 or 3) is needed to determine the pwm period. The following code uses timer 2 for all 8 channels.<br />
void pwm_open(void){<br />
OC1CON = 0; OC2CON = 0; //Disable all output compare modules<br />
OC3CON = 0; OC4CON = 0;<br />
OC5CON = 0; OC6CON = 0;<br />
OC7CON = 0; OC8CON = 0;<br />
//============================================================<br />
TMR2 = 0; // Clear register<br />
PR2 = 0xFFFF; // Set to Maximum<br />
//============================================================<br />
_T2IF = 0; // Clear interrupt flag<br />
_T2IE = 0 // Enable interrupts<br />
//============================================================<br />
T2CONbits.TCS = 0; // Use internal clock source<br />
T2CONbits.TCKPS = 0; // Prescale Select 1:1<br />
//============================================================<br />
T2CONbits.TON = 1; // Start the timer <br />
}<br />
<br />
====ioctl()====<br />
*User should select the channel and set the pwm period using the functions below before issuing the duty cycle:<br />
char pwm_ioctl(unsigned char request, unsigned long* argp){<br />
unsigned int value;<br />
unsigned char mask;<br />
switch(request){<br />
case PWM_SET_PERIOD:<br />
return setPeriodNPrescale(argp[0]);<br />
case PWM_SELECT_CH:<br />
pwm_channel = argp[0];<br />
mask = 0x01 << pwm_channel;<br />
pwm_status = pwm_status | mask;<br />
return 0;<br />
default:<br />
return -1;<br />
}<br />
}<br />
char setPeriodNPrescale(unsigned long value_ns){<br />
unsigned long ans;<br />
unsigned long long numerator = (unsigned long long)value_ns*SYSTEM_FREQ_MHZ;<br />
int index= -1;<br />
unsigned long denominator;<br />
//-------------------------------------------------<br />
do{<br />
denominator = (unsigned long)1000*pwm_prescale[++index];<br />
ans = (unsigned long)(((long double)numerator/denominator) + 0.5) - 1; //round to nearest int<br />
} while(ans > 0x0000FFFF && index < 3);<br />
//-------------------------------------------------<br />
if(ans > 0x0000FFFF)<br />
return -1;<br />
//-------------------------------------------------<br />
T2CONbits.TON = 0; // Turn off the timer<br />
T2CONbits.TCKPS = index; // Change prescale factor<br />
PR2 = (unsigned int) ans; // Set to Maximum<br />
T2CONbits.TON = 1; // Turn on the timer <br />
//-------------------------------------------------<br />
return 0;<br />
}<br />
<br />
====write()====<br />
*User can change the duty cycle using the following functions<br />
int pwm_write(unsigned long* buf){<br />
if((pwm_status & (0x01 << pwm_channel)) == 0){<br />
return -1; //Channel has not been enabled<br />
}<br />
switch(pwm_channel){<br />
case 0:<br />
OC1RS = calcDCycle(buf[0]); OC1R = OC1RS; <br />
OC1CONbits.OCM = 6; //Simple PWM, Fault pin disabled<br />
break;<br />
case 1:<br />
OC2RS = calcDCycle(buf[0]); OC2R = OC2RS; <br />
OC2CONbits.OCM = 6; //Simple PWM, Fault pin disabled<br />
break;<br />
...<br />
case 7:<br />
OC8RS = calcDCycle(buf[0]); OC8R = OC8RS; <br />
OC8CONbits.OCM = 6; //Simple PWM, Fault pin disabled<br />
break; <br />
default:<br />
return -1;<br />
}<br />
return 4;<br />
}<br />
unsigned int calcDCycle(unsigned long value_ns){<br />
unsigned long long numerator = (unsigned long long)value_ns*SYSTEM_FREQ_MHZ;<br />
unsigned int index = T2CONbits.TCKPS;<br />
unsigned long denominator = (unsigned long)1000*pwm_prescale[index];<br />
return (unsigned int)(((long double)numerator/denominator) + 0.5) - 1; //round to nearest int<br />
}<br />
<br />
====Propagration Delay====<br />
*PWM channels sharing the same timer will have their PWM signals synchronised (i.e. the HIGH state of the duty cycle are all triggered together).<br />
*To introduced delay to the PWM signals, the signal from selected channels may be made to pass through a series of inverters (e.g. 74HC14D). This adds propagation delay to the signal.<br />
*However, as propagration delay of logic gates depends on applied voltage, temperature and load capacitance, the accuracy is low and performance is poor. For accurate delay, delay lines may be used, but they are expensive.<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 6.4 Propagation Delay of [http://www.nxp.com/acrobat_download/datasheets/74HC_HCT14_3.pdf Philips 74HC14D]<sup>[1], [2]</sup><br />
! !! 3.3V !! !! !! 5.0V !! !!<br />
|- <br />
! Number of Gates !! A !! B !! C !! A !! B !! C<br />
|- <br />
| 2 <br />
| 21ns (10.5)|| 23ns (11.5)|| 22ns (11.0)<br />
| 15ns (7.5)|| 14ns (7.0)|| 14ns (7.0)<br />
|-<br />
| 4 <br />
| 45ns (11.3)|| 46ns (11.5)|| 46ns (11.5) <br />
| 30ns (7.5)|| 30ns (7.5)|| 30ns (7.5)<br />
|-<br />
| 6 <br />
| 69ns (11.5)|| 70ns (11.7)|| 72ns (12.0) <br />
| 45ns (7.5)|| 46ns (7.7)|| 47ns (7.8)<br />
|- <br />
|}<br />
[1] Data in specification for 4.5V: Typical 15ns, Maximum 25ns<br><br />
[2] Data in specification for 6.0V: Typical 12ns, Maximum 21ns<br />
<br />
===DSP Library===<br />
<br />
----<br />
*Library functions in <dsp.h> include the following categories: <br />
#Vector<br />
#Window<br />
#Matrix<br />
#Filtering<br />
#Transform<br />
#Control<br />
<br />
====Data Types====<br />
*Signed Fractional Value (1.15 data format)<br />
**Inputs and outputs of the dsp functions adopt 1.15 data format, which consumes 16 bits to represent values between -1 to 1-2<sup>-15</sup> inclusive.<br />
**Bit<15> is a signed bit, positive = 0, negative = 1.<br />
**Bit<14:0> are the exponent bits ''e''.<br />
**Positive value = 1 - 2<sup>-15</sup>*(32768 - ''e'')<br />
**Negative value = 0 - 2<sup>-15</sup>*(32768 - ''e'')<br />
*40-bit Accumulator operations (9.31 data format)<br />
**The dsp functions use the 40 bits accumalators during arithmatic calculations.<br />
**Bit<39:31> are signed bits, positive = 0x000, negative = 0x1FF.<br />
**Bit<30:0> are exponent bits.<br />
*IEEE Floating Point Values<br />
**Fractional values can be converted to Floating point values using: '''fo = Fract2Float(fr);''' for fr = [-1, 1-2<sup>-15</sup>]<br />
**Floating point values can be converted to Fractional values using: '''fr = Float2Fract(fo);''' or '''fr = Q15(fo);''' for fo = [-1, 1-2<sup>-15</sup>]<br />
**Float2Fract() is same as Q15(), except having saturation control. When +ve >= 1, answer = 2<sup>15</sup>-1 = 32767 (0x7FFF). When -ve < -1, answer = -2<sup>15</sup> = -32767 (0x8000)<br />
<br />
===Build-in Library===<br />
<br />
----<br />
*Some assembler operators can only be accessed by inline assembly code, for example, <br />
#Manuipulation of accumulators A and B (add, sub, mul, divide, shift, clear, square)<br />
#Bit toggling<br />
#Access to psv (program space visiblity) page and offset<br />
#Access to table instruction page and offset<br />
*Built-in functions are written as C-like function calls to utilize these assembler operators.<br />
<br />
<br />
==Bootloader Development==<br />
<br />
===Concepts===<br />
*Programming with ICSP is useful when the target board is produced in batch. The producer can download a program even when the chip is on the target board.<br />
*However, ICSP requires an external programmer.<br />
*To allow the user to change the program after production but without the need of an external programmer, bootloader becomes useful.<br />
*Bootloader is a small program installed via ICSP. Everytime the device is reset, the bootloader is run first. The bootloader first detects the default serial channel whether the user wishes to download a new program to the device. If so, the bootloader will pause there, and wait for the user to download the hex file from the PC. The hex file is written to the device via RTSP instructions in the bootloader. If a new download is not necessary, the bootloader redirects to the previously installed user's program.<br />
*The disadvantage of bootloaders is that they consume some of the memory of the device.<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 7.1 Free bootloaders for dsPIC<br />
! Developer<br />
! Source<br />
! Platform<br />
! User Guide<br />
! Remarks<br />
|- valign="top"<br />
| [http://www.ingenia-cat.com/index.php?lang=en ingenia]<br />
| [http://www.ingenia-cat.com/download/iBL.s Assembly]<br />
| [http://www.ingenia-cat.com/download/ingeniadsPICbootloader1.1.zip Windows]<br />
| [http://www.ingenia-cat.com/reference/pdf/iBL.UG.V1.2.pdf pdf]<br />
| <br />
*Works for all dsPIC supporting RTSP<br />
*Auto baudrate detection<br />
*Use about 1.15% of the flash memory space (0xAFFF-0xAE00)/(0xAFFF-0x0100)<br />
*Development of Linux platform is underway<br />
*Modification of code for dsPIC30F5011 is successful<br />
|-valign="top"<br />
| [http://www.etc.ugal.ro/cchiculita/software/picbootloader.htm Tiny]<br />
| [http://www.etc.ugal.ro/cchiculita/software/tinybld191.zip Assembly]<br />
| Windows<br />
| [http://www.etc.ugal.ro/cchiculita/software/tinybldusage.htm Web]<br />
| <br />
*By default, only supports 601X, 601X, 401X, 2010<br />
*Smaller code size than ingenia, but not as easy to modify<br />
|-valign="top"<br />
| [http://www.via.si/software/dsPIC_bootloader/ Elektronika]<br />
| [http://www.via.si/software/dsPIC_bootloader/data/ Hex]<br />
| Windows<br />
| [http://www.via.si/software/dsPIC_bootloader/data/README.txt txt]<br />
| <br />
*Only works for dsPIC30F6014 serial port UART2 at baudrate 57600<br />
|-<br />
|}<br />
<br />
===dsPicBootloader===<br />
<br />
*The bootloader developed by ingenia is open source and it has been modified (see below) to suit our development using dsPic30f5011.<br />
*The bootloader (hereafter called dsPicBootloader) employs the following settings:<br />
# Use U2ART channel<br />
# Use FRC, PLL16<br />
# For 5011, the bootloader is located between 0x00AE00 to 0x00AFFE (512bytes). Refer to C:\Program Files\Ingenia\ingeniadsPICbootloader\ibl_dspiclist.xml after installing the GUI interface.<br />
*Changes made to [http://www.ingenia-cat.com/download/iBL.s assembly code] includes:<br />
1. including p30f5011.gld and p30f5011.inc<br />
.include "p30f5011.inc"<br />
2. changing the config code of UART #0x8420 -> #0x8020<br />
; Uart init<br />
mov '''#0x8020''', W0 ; W0 = 0x8020 -> 1000 0000 0010 0000b<br />
mov W0, U2MODE ; Enable UART, AutoBaud and 8N1<br />
clr U2STA<br />
3. changing the start address 0xAE00 - 0x0100 = 0AD00<br />
.equ CRC, W4<br />
.equ ACK, 0x55<br />
.equ NACK, 0xFF<br />
.equ USER_ADDRESS, 0x0100<br />
.equ START_ADDRESS, '''0xAD00''' ; Relative to 0x0100<br />
4. using Internal FRC and PLL16<br />
config __FOSC, CSW_FSCM_OFF & '''FRC_PLL16''' ;Turn off clock switching and<br />
;fail-safe clock monitoring and<br />
;use the Internal Clock as the<br />
;system clock<br />
5. disabling MCLR (optional)<br />
config __FBORPOR, PBOR_ON & BORV_27 & PWRT_16 & '''MCLR_DIS'''<br />
;Set Brown-out Reset voltage and<br />
;and set Power-up Timer to 16msecs<br />
6. changing all the related registers of U1ART to U2ART, all U1XXX => U2XXX<br />
'''U2MODE, U2STA, U2BRG, U2RXREG, U2TXREG'''<br />
7. changing all the related registers of IC1 to IC2, all IC1XXX => IC2XXX<br />
'''IC2CON, #IC2IF, #IC2IE'''<br />
<br />
===dsPicProgrammer (Java-based Multi-Platformed)===<br />
*Ingenia developed a programmer (PC-side) that works only in Windows environment. The project for Linux environment is currently suspended.<br />
*A simple programmer (hereafter called dsPicProgrammer) written in Java based on the library developed by [http://www.rxtx.org/ RXTX] has been developed here. The programmer supports both Linux and Windows environments, and may be used as a substitution for the official programmer developed by ingenia.<br />
*The programmer has the following specification and limitations:<br />
#Can be used on both Linux and Windows platforms.<br />
#Adjustable baudrate (9600bps to 57600bps).<br />
#Support programming of dsPIC30F5011 and dsPIC33FJ128GP306 devices (Developers may add your devices).<br />
#Protection against overwriting bootloader codes on devices.<br />
#Detection if application program does not have its reset() at user's code start address.<br />
#Reprogramming can be done without powering down the target board, provided the user's program is compliant to that stated below.<br />
#Target board will run the user's program after programming is done.<br />
#Can be used with USB-Serial Cables. Below is a list of tested cable:<br />
::[http://www.prolific.com.tw/eng/Products.asp?ID=59 Prolific PL-2303 USB to Serial Bridge Controller]: [http://www.prolific.com.tw/eng/downloads.asp?ID=31 Driver download]<br />
<br />
===Special Consideration===<br />
*The bootloader assumes that the user program starts at address 0x100. This is usually the case, but there are always exceptions.<br />
*To ensure that the user program always starts at address 0x100, you can create a customized linker script and customized reset() function as follows:<br />
:*Copy and modify the file named "crt0.s" from the directory "C:\Program Files\Microchip\MPLAB C30\src\pic30" to the project directory and include it.<br />
.section .reset, code //previously .section .libc, code <br />
:*Copy and modify the linkerscript for the device (e.g. p30f5011.gld) to the project directory and include it.<br />
.text __CODE_BASE :<br />
{<br />
*(.reset); //<-insert this line here<br />
*(.handle);<br />
*(.libc) *(.libm) *(.libdsp); /* keep together in this order */<br />
*(.lib*);<br />
*(.text);<br />
} >program<br />
<br />
===Communication Protocol===<br />
<br />
+-------------------+ +-------------------+----------------+<br />
| dsPicProgrammer | | dsPicBootloader | User's Program |<br />
+-------------------+ +-------------------+----------------+<br />
| PC | | Target dsPic |<br />
+-------------------+ +------------------------------------+<br />
| COM PORT |=============| UART |<br />
+-------------------+ +------------------------------------+<br />
<br />
* '''Stage 1: User's Configuation'''<br />
**Select a COM port channel<br />
**Select a baudrate<br />
**Select the user hex file<br />
java -jar dsPicProgrammer.jar COM1 19200 foo.hex<br />
* '''Stage 2: Resetting Target Device'''<br />
**dsPicProgrammer sends a Break character (pull UART-TX to low logic, which is normally high).<br />
**User's program on dsPic detects the break character and reset the chip<br />
::NOTE: The user's program is expected to have the following code in order to enable this function. Otherwise, the target board must be restarted manually.<br />
void _ISR _U2RXInterrupt(void)<br />
{<br />
//No Framming error<br />
if( U2STAbits.FERR == 0)<br />
{<br />
//Normal procedure<br />
}<br />
//Framming error<br />
else<br />
{<br />
if ( U2STAbits.URXDA ){<br />
unsigned char data;<br />
data = (unsigned char) U2RXREG;<br />
if(data == 0x00){<br />
// A break char has been received: <br />
// U2RX has been pulled to zero for more than 13 bits<br />
// This is used to reboot the pic<br />
mdelay(800); //wait for break character to clear<br />
asm("reset"); //software reset<br />
}<br />
} <br />
}<br />
_U2RXIF = 0; //Clear the flag<br />
}<br />
* '''Stage 3: Entering Ingenia's Protocol'''<br />
** Transmission is conducted in 8N1, i.e. 8-bit, no parity, 1 stop-bit<br />
** Communication Protocol is reviewed in [http://www.ingenia-cat.com/reference/pdf/iBL.UG.V1.2.pdf ingenia bootloader user's guide] section 2.1.3. The following summarises the key steps on the PC side (Refer also to section 2.2.2).<br />
::#Autobaud rate detection: dsPicProgrammer continuously sends a character "U" [0x55] via COM port and waits for an acknowledgment character "U", [ACK] = [0x55]<br />
::#Version Control: dsPicProgrammer sends the command character [0x03]. On success, dsPicProgrammer receives 3 characters i) Major Version ii) Minor Version iii) Acknowledgment [0x55]<br />
::#Device ID Monitoring: dsPicProgrammer sends the read command character [0x01] + 24-bit address [High][Medium][Low] (0xFF0000). Then, it receives 4-byte data [High][Medium][Low][ACK]<br />
::#Load the user hex file and check integrity<br />
::#Start Programming: dsPicProgrammer issues the write command character [0x02] + 24-bit address [High][Medium][Low]+ Number of bytes [N] + [data 0] + [data 1] + ... + [data N-1] + [CRC]=(INTEL HEX8 Checksum - Sum modulo 256) and receives [ACK] or [NACK] = [0xFF]<br />
::NOTE: Writing is in row mode access (i.e. erase and write a whole row, each row has 32 instructions, or 96 bytes because each instruction has 24 bits)<br />
* '''Stage 4: Goto User's Program'''<br />
**dsPicProgrammer sends the goto user code command [0x0F]<br />
<br />
<br />
==USB-RS232 Bridge==<br />
<br />
*As USB ports are becoming more and more common, COM ports and Parallel ports may be redundant in the next few years. This section explore the possibilities of programming the target board through a USB port.<br />
*There are two options:<br />
#Use an external USB/RS232 adaptor, the driver will emulate a virtual COM port, such as [http://www.prolific.com.tw/eng/downloads.asp?ID=31 Prolific] and [http://www.ftdichip.com/Drivers/VCP.htm FDTI]. Ingenia has tested its bootloader with some USB-232 manufacturers (silabs, FTDI, etc..). However, the programming failed with our Prolific adapter. Application program may use [http://java.sun.com/products/javacomm/ JavaComm API] (javax.comm) and/or [http://www.rxtx.org/ RXTX] to drive the COM port.<br />
#Modified the bootloader program on PC to support USB communication. e.g. using [http://jusb.sourceforge.net/ jUSB] and [http://javax-usb.org/ JSR-80] (javax.usb). External circuits such as PIC18F4550 and MAX232 are required.<br />
<br />
|--User's App.--|-------Device Manager------|-------USB-RS232 Interface------|---dsPIC---|<br />
Option 1:<br />
+-------------+ +----------+ +----------+ +---+ +------------+ +-----+ +--------+<br />
| Application |--| JavaComm |--| Virtual |==|USB|--| FDTI |--|RS232|==| Target |<br />
| Program | | RXTX | | COM Port | +---+ | Circuitary | +-----+ | Board |<br />
+-------------+ +----------+ +----------+ +------------+ +--------+<br />
Option 2:<br />
+-------------+ +--------+ +---+ +------------+ +-----+ +--------+<br />
| Application |----------| JSR-80 |==========|USB|--| PIC18F4550 |--|RS232|==| Target |<br />
| Program | | jUSB | +---+ | MAX232 | +-----+ | Board |<br />
+-------------+ +--------+ +------------+ +--------+<br />
<br />
*Currently, when RXTX is incorporated with JavaComm API, operating systems supported include Linux, Windows, Mac OS, Solaris and other operating systems. On the other hand, jUSB and JSR-80 only works for linux.<br />
<br />
===FDTI Chipset===<br />
*FT232RL communicates with PC via USB to provide 1 UART channel.<br />
*Datasheet can be downloaded [http://www.ftdichip.com/Documents/DataSheets/DS_FT232R.pdf here]. <br />
**Refer to Fig. 11 (Page 19) for Bus Powered Configuration.<br />
**Refer to Fig. 16 (Page 24) for for UART TTL-level Receive [RXD -> 1], Transmit [TXD -> 4], Transmit Enable [CBUS2/TXDEN -> 3]. Omit Receive Enable [CBUS3/PWREN#] and use [CBUS2/TXDEN -> 2] <br />
**Refer to Fig. 15 (Page 23) for LED Configuration: [CBUS0/TXLED#] and [CBUS1/RXLED#]<br />
*Virtual COM Port Drivers can be downloaded [http://www.ftdichip.com/Drivers/VCP.htm here].<br />
<br />
<br />
==Programming the Device==<br />
<br />
===Requirements===<br />
*Hardware<br />
#PC with COM port (Windows XP Installed for MPLAB)<br />
#ICD2 Programmer<br />
#Target Board<br />
#5V Power Supply<br />
<br />
*Software<br />
#[http://ww1.microchip.com/downloads/en/DeviceDoc/MP750.zip MPLAB IDE v7.50]: v7.60 is not compatible with our current [http://www.sure-electronics.com/ ICD2 Programmers]. There are consistent "Devices cannot be founded" warnings.<br />
#[http://chungyan5.no-ip.org/websvn/listing.php dsPicProgrammer] ('''dsPicProgrammer.jar''')<br />
#[http://users.frii.com/jarvi/rxtx/download.html RXTX driver]: download and upzip rxtx-2.1-7-bins-r2.zip (Final)<br />
<br />
*Files<br />
#[http://chungyan5.no-ip.org/websvn/listing.php dsPicBootloader] ('''bl_5011.hex'''). Original assembly code by ingenia can be downloaded from [http://www.ingenia-cat.com/download/iBL.s here].<br />
#Application hex file (e.g. '''app.hex''')<br />
<br />
===Loading Bootloader (Once only)===<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 9.1 Loading Bootloader<br />
! Step !! Remarks <br />
|-valign="top"<br />
| Install [http://ww1.microchip.com/downloads/en/DeviceDoc/MP750.zip MPLAB IDE] || <br />
*Do '''NOT''' connect ICD 2 (via USB) to PC<br />
*Execute '''MPLAB vX.XX Install.exe'''<br />
|-valign="top"<br />
| Install USB Driver ||<br />
*Follow the instruction in (C:\Program Files\Microchip\MPLAB IDE\ICD2\Drivers\Ddicd2.htm)<br />
|-valign="top"<br />
| Select Target Chip ||<br />
*Run MPLAB IDE on PC<br />
*Select: Configure>Select Devices...<br />
*Choose dsPIC30F5011<br />
|-valign="top"<br />
| Target <-> ICD 2 ||<br />
*Use six pin cable. Beware of the pin assignments. Only pin 1 - 5 should be used.<br />
*Place Jumper on target board (if any). The Jumper connects target V<sub>cc</sub> to ICD 2.<br />
*Do '''NOT''' power-up the target.<br />
|-valign="top"<br />
| ICD 2 <-> PC ||<br />
*Plug-in ICD 2 to PC via USB cable<br />
*Power-up the target.<br />
*Select: Programmer>Select Programmer>MPLAB ICD 2<br />
*If this is the first time the ICD 2 is connected to PC, MPLAB IDE will automatically download the required OS to ICD 2, wait until it has finished<br />
*If you have not connected and powered up the target, you might see Warnings on invalid device IDs, and/or running self tests.<br />
*See results of self test if necessary: Programmer>Settings, Status Tab. Refer to [http://ww1.microchip.com/downloads/en/DeviceDoc/51331B.pdf ICD2 User's Guide] Chapter 7.<br />
|-valign="top"<br />
| Load Bootloader ||<br />
*Select: File>Import...<br />
*Select '''bl_5011.hex'''<br />
|-valign="top"<br />
| Start Programming ||<br />
*Select: Programmer>Program<br />
|-valign="top"<br />
| Finishing ||<br />
*Power-down the Taget<br />
*Select: Programmer>Select Programmer>None<br />
*Unplug USB cable<br />
|-<br />
|}<br />
<br />
===Loading Firmware===<br />
<!--using Firefox-File-Page_Setup-Format-Scale-85% to print --><br />
====Java Environment Setup====<br />
*Download and install the latest JDK or JRE<br />
**Available from [http://java.sun.com/javase/downloads/index.jsp Sun Microsystems] (e.g. JDK 6 Update 3)<br>[[Image:1 1 java.JPG]]<br><br />
*Download and Extract RXTX Driver <br />
**Available from [http://users.frii.com/jarvi/rxtx/download.html RXTX] <br />
**File: rxtx-2.1-7-bins-r2.zip (Final)<br />
**Extract the files using software such as WinRAR<br>[[Image:1 2 rxtx.JPG]]<br><br />
*Copy RXTXcomm.jar<br />
**To C:\Program Files\Java\X\lib\ext (under the latest jre, e.g. X = jre1.6.0_03)<br>[[Image:1 3 rxtxcomm.JPG]]<br><br />
*Copy rxtxSerial.dll<br />
**To C:\Program Files\Java\X\bin (under the lastest jre, e.g. X = jre1.6.0_03)<br />
**For Linux users, copy librxtxSerial.so to /jre/lib/[machine type] (i386 for instance)<br>[[Image:1 4 rxtxserial.JPG]]<br><br />
*Download dsPicProgrammer <br />
**Available from [http://chungyan5.no-ip.org/websvn/listing.php?repname=repos+1&path=%2FdsPicProgrammer%2Ftags%2F&rev=0&sc=0 here]<br />
**Expand the latest tag under dsPicProgrammer<br />
**File: dsPicProgrammer.jar<br>[[Image:1 5 dspicprogrammer.JPG]]<br><br />
**Save the file (dsPicProgrammer.jar) and your hex file (foo.hex) to your local directory (e.g. C:\dsPicProgrammer\)<br>[[Image:1 6 dspicprogrammer2.JPG]]<br><br />
<br />
====Download Firmware====<br />
*Start a Command Prompt<br />
**Start -> Run<br>[[Image:2 1 run.JPG]]<br><br />
**Enter cmd<br>[[Image:2 2 cmd.JPG]]<br><br />
*Run dsPicProgrammer<br />
**Make sure your device is connected through a "Direct RS232 Cable" to PC Serial Port. <br />
**Change to the directory where dsPicProgrammer.jar is located and run the command:<br>java -jar dsPicProgrammer.jar COM1 57600 foo.hex (Windows)<br>java -jar dsPicProgrammer.jar /dev/ttyS0 57600 foo.hex (Linux)<br>where COM1 is your COM Port ID<br>57600 is communication speed [in bps]<br>foo.hex is your firmware new file<br>[[Image:2 3 command.JPG]]<br><br />
**When the program prompt you for an input, press y:<br>[[Image:2 4 prompt.JPG]]<br><br />
**If communication can be established, you should see something like this:<br>[[Image:2 5 progress.JPG]]<br><br />
**Wait until programming is completed.<br>[[Image:2 6 complete.JPG]]<br><br />
**after all completed, power OFF your device, then power ON again, enjoy your new updated.<br />
<br />
====Troubleshooting====<br />
*Invalid COM Port<br />
**In case of selecting an invalid COM port, you should see the error message:<br>gnu.io.NoSuchPortException: Choosing COM Port Error<br>[[Image:3 1 com err.JPG]]<br><br />
*Missing firmware file<br />
**In case of selecting a firmware file that does not exist, you should see the error message:<br>java.io.FileNotFoundException: foo1.hex <The system cannot find the file specified><br>[[Image:3 2 file err.JPG]]<br><br />
*Missing RXTX driver<br />
**In case of missing the RXTX driver, you should see the error message:<br>Exception in thread “main” java.lang.NoClassDefFoundError: gnu/io/UnsupportedCommOperationException<br>[[Image:3 3 rxtx err.JPG]]<br><br />
<br />
==Remote Access==<br />
*At the moment, local devices (e.g. EEPROM, ADC, DAC, etc.) can only be accessed locally through POSIX functions such as open(), read(), write(), ioctl().<br />
*However, a client may need to access these devices on a remote server. This section reviews the background and gives some ideas on its possible implementation.<br />
<br />
===Requirements===<br />
*A remote file access protocol, to transfer "files" (i.e. device's data) such as:<br />
#[http://en.wikipedia.org/wiki/FTP File Transfer Protocol] (FTP): Required files are copied from sever to client for manipulation<br />
#[http://en.wikipedia.org/wiki/Remote_Shell Remote Shell] (RSH): Required files are copied from sever to client for manipulation<br />
#[http://en.wikipedia.org/wiki/Network_File_System_%28Sun%29 Network File System] (NFS): Required files are manipulated on sever<br />
*An API to access files using a selected protocol, such as:<br />
#[http://www.die.net/doc/linux/man/man2/lam_rfposix.2.html lam_rfposix]: A POSIX-like remote file service for Local Area Multicomputer<br />
#API employed by VxWorks: [http://en.wikipedia.org/wiki/VxWorks VxWorks] is a Unix-like real-time operating system, commonly used for embedded systems.<br />
<br />
===API Reference for VxWorks===<br />
*Reference:<br />
**[http://www.windriver.com/vxworks/ VxWorks Official Website]<br />
**[http://www-cdfonline.fnal.gov/daq/commercial/ OS Libraries API Reference]<br />
*Related Libraies<br />
**netDrv (netDrv.h): an API using FTP or RSH<br />
**nfsDrv (nfsDrv.h): an API using NFS<br />
<br />
<br />
==Conversion to dsPIC33F Devices==<br />
*This section discusses the conversion required from dsPIC30F5011 to dsPIC33FJ128GP306.<br />
*Refer to official document [http://ww1.microchip.com/downloads/en/DeviceDoc/70172A.pdf dsPIC30F to dsPIC33F Conversion Guidelines] (DS70172A).<br />
*Note that this section does not mainly intend to introduce the new functionalities of dsPIC33F devices. It only serves the purpose to summarise the major (if not minimum) changes required to port the setup of dsPIC30 to dsPIC33 devices.<br />
<br />
===Hardware===<br />
*dsPIC33 operates at voltage of 3.3V. A voltage regulator, such as [http://www.national.com/ds.cgi/LM/LM3940.pdf LM3940] can be used to convert 5V supply to 3.3V.<br />
*A 1uF capacitor has to be placed at pin 56 (previously V<sub>SS</sub>, now V<sub>DDCORE</sub>).<br />
<br />
===Software===<br />
<br />
====Configuration Bits====<br />
<br />
----<br />
*dsPIC33 can operate at 40MIPs at maximum. To configure the device using internal FRC, replace the configuration bits setting as follows:<br />
_FOSCSEL(FNOSC_FRCPLL); // FRC Oscillator with PLL<br />
_FOSC(FCKSM_CSDCMD & OSCIOFNC_ON & POSCMD_NONE); <br />
// Clock Switching and Fail Safe Clock Monitor is disabled<br />
// OSC2 Pin Function: OSC2(RC15) as Digital IO<br />
// Primary Oscillator Mode: Disabled<br />
_FWDT(FWDTEN_OFF); // Watchdog Timer Enabled/disabled by user software <br />
*Configure on-chip PLL at runtime as follows (at start of main function):<br />
_PLLDIV = 38; // M=40: PLL Feedback Divisor bits<br />
CLKDIV = 0; // N1=2: PLL VCO Output Divider Select bits<br />
// N2=2: PLL Phase Detector Input Divider bits<br />
OSCTUN = 22; // Tune FRC oscillator, if FRC is used; <br />
// 0: Center frequency (7.37 MHz nominal)<br />
// 22: +8.25% (7.98 MHz)<br />
RCONbits.SWDTEN = 0; // Disable Watch Dog Timer<br />
while(OSCCONbits.LOCK != 1); // Wait for PLL to lock<br />
<br />
====UART====<br />
<br />
----<br />
*No change is required.<br />
<br />
====I2C====<br />
<br />
----<br />
*dsPIC33 supports upto 2 I<sup>2</sup>C devices. As a result, replace all I<sup>2</sup>C related registers with xxI2Cyy to xxI2C'''1'''yy. For examples:<br />
_SI2C1IF = 0; //Clear Slave interrupt<br />
_MI2C1IF = 0; //Clear Master interrupt<br />
_SI2C1IE = 0; //Disable Slave interrupt<br />
_MI2C1IE = 0; //Disable Master interrupt<br />
I2C1BRG = I2C_BRG; // Configure Baud rate<br />
I2C1CONbits.I2CEN = 1;<br />
...<br />
etc.<br />
<br />
====ADC====<br />
<br />
----<br />
*The ADC in dsPic33 is significantly different from that in dsPic30. Specifically, ADC in dsPic33 uses DMA to buffer the adc data. Replace the open, interrupt routine, add and remove codes as follows:<br />
<br />
unsigned int adc_bufA[ADC_MAX_CH] __attribute__((space(dma),aligned(256)));<br />
unsigned int adc_bufB[ADC_MAX_CH] __attribute__((space(dma),aligned(256)));<br />
unsigned int* ADC16Ptr; //Pointer to ADC register buffer, <br />
unsigned char adc_ch_select = 0; //Pointer to channel to be read from<br />
unsigned char adc_data_ready = 0; //Indicate if RAM data is ready for output<br />
unsigned int which_dma = 0; //indicate which adc_buf to be used<br />
<br />
void adc_open(void)<br />
{<br />
// Configure interrupt<br />
_AD1IF = 0; //clear ADC interrupt flag<br />
_AD1IE = 0; //disable adc interrupt<br />
AD1CHSbits.CH0NA = 0;<br />
// Configure analog i/o <br />
_TRISB0 = 1;<br />
_TRISB1 = 1; <br />
AD1PCFG = 0xFFFC; //Enable AN0 (Vref+) and AN1 (Vref-)<br />
AD1PCFGH = 0xFFFF; //AN16-AN31: Disabled<br />
// Configure scan input channels <br />
AD1CSSL = 0x0003; //0 => Skip, 1 => Scan<br />
AD1CSSH = 0x0000; //Skipping AN16-AN31<br />
// ADCCON4:<br />
AD1CON4bits.DMABL = 0; // Each buffer contains 1 word<br />
// ADCCON3:<br />
AD1CON3bits.SAMC = 1; //1TAD for sampling time<br />
AD1CON3bits.ADRC = 0; //Use system clock<br />
AD1CON3bits.ADCS = ADC_ADCS; //each conversion requires 14TAD<br />
// ADCCON2:<br />
AD1CON2bits.VCFG = 3; //External Vref+, Vref-<br />
AD1CON2bits.CSCNA = 1; //Scan input<br />
AD1CON2bits.SMPI = 1; //2 channels are scanned<br />
// ADCCON1:<br />
AD1CON1bits.FORM = 0; //[0:integer]; [2 fractional]; [3 siged fractional]<br />
AD1CON1bits.SSRC = 7; //auto covert, using internal clock source<br />
AD1CON1bits.ASAM = 1; //auto setting of SAMP bit<br />
AD1CON1bits.AD12B = 1; //12-bit, 1-channel ADC operation<br />
AD1CON1bits.ADDMABM = 0; // DMA buffers are built in scatter/gather mode<br />
AD1CON1bits.ADON = 1; // Turn on the A/D converter<br />
// DMA0 Configuration:<br />
DMA0CONbits.AMODE = 2; // Configure DMA for Peripheral indirect mode<br />
DMA0CONbits.MODE = 2; // Configure DMA for Continuous Ping-Pong mode<br />
DMA0PAD=(int)&ADC1BUF0; <br />
DMA0CNT = 1; // generate dma interrupt every 2 samples <br />
// same as SMPI because only 1 dma buffer per channel <br />
DMA0REQ = 13; // Select ADC1 as DMA Request source<br />
DMA0STA = __builtin_dmaoffset(adc_bufA); <br />
DMA0STB = __builtin_dmaoffset(adc_bufB);<br />
_DMA0IF = 0; // Clear the DMA interrupt flag bit<br />
_DMA0IE = 1; // Set the DMA interrupt enable bit<br />
DMA0CONbits.CHEN=1; // Enable DMA<br />
}<br />
<br />
void _ISR _DMA0Interrupt(void)<br />
{<br />
ADC16Ptr = (which_dma == 0)? adc_bufA : adc_bufB; //Update pointer<br />
adc_data_ready = 1;<br />
which_dma ^= 1; //Next buffer to be used<br />
_DMA0IF = 0; //Clear the DMA0 Interrupt Flag<br />
}<br />
<br />
static void adcAdd(unsigned char ch){<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
TRISB = TRISB | mask;<br />
AD1CSSL = AD1CSSL | mask; <br />
AD1PCFG = ~AD1CSSL;<br />
AD1CON2bits.SMPI++; //take one more sample per interrupt<br />
DMA0CNT++; <br />
}<br />
<br />
static void adcRm(unsigned char ch){<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
AD1PCFG = AD1PCFG | mask;<br />
AD1CSSL = ~AD1PCFG;<br />
AD1CON2bits.SMPI--; //take one less sample per interrupt<br />
DMA0CNT--; <br />
}<br />
<br />
====EEPROM====<br />
<br />
----<br />
*There is no EEPROM in dsPIC33 devices. Please consider to use an external EEPROM using I<sup>2</sup>C communication.<br />
<br />
====Simple PWM====<br />
<br />
----<br />
*No change is required.<br />
<br />
===Memory Map for dsPIC33FJ128GP306===<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 11.1 Memory Location<br />
! Type !! Start Address !! End Address !! Size<br />
|-valign="top"<br />
| Flash || 0x000000 ||0x0157FF || 86K<sup>[1]</sup><br />
|-valign="top"<br />
| +--Flash: Reset Vector || 0x000000 ||0x000003 || 4<br />
|-valign="top"<br />
| +--Flash: Interrupt Vector Table || 0x000004 ||0x0000FF || 252<br />
|-valign="top"<br />
| +--Flash: Alternate Vector Table || 0x000104 ||0x0001FF || 252<br />
|-valign="top"<br />
| +--Flash: User Program || 0x000200 ||0x0157FF || 85.5K<br />
|-valign="top"<br />
| Programming Executive || 0x800000 || 0x800FFF || 4K<sup>[1]</sup><br />
|-valign="top"<br />
| Config Registers || 0xF80000 || 0xF80017 || 24<br />
|-valign="top"<br />
| Device ID (0xE5) || 0xFF0000 || 0xFF0003 || 4<br />
|-<br />
|}<br />
[1] Each address is 16-bit wide. Every two addresses correspond to a 24-bit instruction. Each even address contains 2 valid bytes; each odd address contains 1 valid byte plus 1 phathom byte.<br><br />
<br />
===Custom Linker Script to Maximize Space for Constant Data===<br />
*Constant data declared using keyword '''const''' will be stored in the .const section in the flash memory.<br />
*Normally, during compilation, the linker will assign these data after the program code (.text section).<br />
*Since .const is accessed by auto-psv function, to maximize the space for constant data (32kb), the .const section needs to be aligned at 0x80000 boundary.<br />
*This requires the following change in linker script:<br />
<br />
__CONST_BASE = 0x8000;<br />
<br />
.text __CODE_BASE :<br />
{<br />
*(.reset);<br />
*(.handle);<br />
*(.libc) *(.libm) *(.libdsp); /* keep together in this order */<br />
*(.lib*);<br />
/* *(.text); deleted to maximize space for const data */<br />
} >program<br />
<br />
.const __CONST_BASE :<br />
{<br />
*(.const);<br />
} >program<br />
<br />
*If your program is large, after this change in linker script, function calls may involve large jump in the memory map (>32kB). As a result, you may need to enable the large code and large memory model during compilation. In such case, use the following options in your build path:<br />
-mlarge-code -mlarge-data<br />
*Meanwhile, functions that are defined in the standard C libraries, but are replaced with your own implementations (e.g. I/O stubs: open(), read(), write(), lseek(), ioctl() etc.) may have the following linker error:<br />
/usr/pic30-elf/lib//libc-elf.a(fflush.eo)(.libc+0x3c): In function '.LM11':<br />
: Link Error: relocation truncated to fit: PC RELATIVE BRANCH _write<br />
/usr/pic30-elf/lib//libc-elf.a(fclose.eo)(.libc+0x42): In function '.LM18':<br />
: Link Error: relocation truncated to fit: PC RELATIVE BRANCH _close <br />
*To resolve the problem, you need to place the functions in the .libc section rather than in the .text section, like this:<br />
#define LIBC_CODE_LOC __attribute__ ( (section(".libc")))<br />
<br />
int LIBC_CODE_LOC open(const char *pathname, int flags){ ... }<br />
int LIBC_CODE_LOC close(int fd){ ... }<br />
int LIBC_CODE_LOC write(int fd, void* buf, int count) { ... }<br />
int LIBC_CODE_LOC read(int fd, void* buf, int count) { ... }<br />
int LIBC_CODE_LOC ioctl(int fd, int request, void* argp) { ... }<br />
int LIBC_CODE_LOC lseek(int fd, int offset, int whence) { ... }<br />
<br />
===dsPicBootloader and dsPicProgrammer===<br />
*RTSP for dsPIC33F is different from dsPIC30F.<br />
**Row size changes from 32 instructions (96bytes) to 64 instructions (192 bytes)<br />
**Erase operation changes from 1 row to 8 rows<br />
**No EEPROM<br />
*With regards to the above changes, dsPicBootloader and dsPicProgrammer has been modified. In particular, dsPicProgrammer can be used to program both dsPic30F and dsPic33F devices. You can easily add your devices to the source code.<br />
<br />
<br />
==Downloads==<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 12.1 Related software download links for dsPicBootloader and dsPicProgrammer<br />
! Program<br />
! Site 1<br />
! Site 2<br />
! Remarks<br />
|- valign="top"<br />
| JDK<br />
| [http://java.sun.com/javase/downloads/index.jsp website]<br />
| <br />
| Download latest JDK<br />
|- valign="top"<br />
| RXTX<br />
| [http://users.frii.com/jarvi/rxtx/download.html website]<br />
| <br />
| Download rxtx-2.1-7-bins-r2.zip or later<br />
|- valign="top"<br />
| dsPicBootloader v1.3<br />
| [http://chungyan5.no-ip.org/websvn/listing.php click]<br />
| [http://www.opencircuits.com/images/a/a7/DsPicBootloader_1_3_1.zip click]<br />
| Under "dsPicBootloader/", download bl_5011.s or bl_j128gp306.s<br />
|-valign="top"<br />
| dsPicProgrammer v1.3.5<br />
| [http://chungyan5.no-ip.org/websvn/listing.php click]<br />
| [http://www.opencircuits.com/images/9/9e/DsPicProgrammer_1_3_5.zip click]<br />
| Under "dsPicProgrammer/", dowload dsPicProgrammer.jar<br><br>Alternatively, if you want to compile yourself or modify the source code, download <br>all source files under "dsPicProgrammer/" '''plus''' RdFileIntelHex.java under <br>"IntelHexPaser/tags/0.02.00/".<br>You should also install RXTX on your local machine as recommended in the readme file.<br />
|- valign="top"<br />
| Ingenia's bootloader<br />
| [http://www.ingenia-cat.com/en/downloads.php website]<br />
| <br />
| Download original ingenia's bootloader<br />
|-<br />
|}</div>Yanhttp://www.opencircuits.com/index.php?title=DsPIC30F_5011_Development_Board&diff=14582DsPIC30F 5011 Development Board2008-02-20T07:16:56Z<p>Yan: /* Loading Firmware */ adding the printing scale under firefox</p>
<hr />
<div>==Introduction==<br />
<br />
===Features of dsPIC30F5011===<br />
*2.5 to 5V <br />
*Up to 30MIPs<br />
*High current/sink source I/O pins: 25mA<br />
*DSP Instruction Set<br />
*Dual programming techniques: ICSP and RTSP<br />
*UART: up to 2 modules<br />
*I<sup>2</sup>C: up to 1Mbps<br />
*10-bit A/D, 1.1 Msps <br />
*12-bit A/D, 200 ksps<br />
*44K flash (66Kb), 4Kb RAM, 1Kb EEPROM<br />
*No DAC<br />
*Pin-to-pin compatible with other dsPICs<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 1.1 Comparison with Compatible dsPICs<br />
! dsPic !! Price<br>US$ !! MIPs<br />
! Flash<br>(kB)!! RAM<br>(kB) !! EEPROM<br>(kB)<br />
! I/O !! ADC<br>12-bit !! IC !! OC !! Motor<br>Ctrl !! Timers<br />
! QEI !! UART !! SPI !! I2C !! CAN !! Codec<br />
|- <br />
| 30F5011 || 5.91 || 30<br />
| 66 || 4 || 1<br />
| 52 || 16 || 8 || 8 || 0 || 5x16bit<br>2x32bit<br />
| 0 || 2 || 2 || 1 || 2 || 1<br />
|-<br />
| 30F6011A || 7.73 || 30<br />
| 132 || 6 || 2<br />
| 52 || 16 || 8 || 8 || 0 || 5x16bit<br>2x32bit<br />
| 0 || 2 || 2 || 1 || 2 || 0<br />
|-<br />
| 30F6012A || 7.85 || 30<br />
| 144 || 8 || 4<br />
| 52 || 16 || 8 || 8 || 0 || 5x16bit<br>2x32bit<br />
| 0 || 2 || 2 || 1 || 2 || 1<br />
|- <br />
| 33FJ128GP206 || 4.62 || 40<br />
| 128 || 8 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 1 || 0 || 1<br />
|-<br />
| 33FJ128GP306 || 4.81 || 40<br />
| 128 || 16 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 2 || 0 || 1<br />
|-<br />
| 33FJ128GP706 || 5.49 || 40<br />
| 128 || 16 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 2 || 2 || 1<br />
|-<br />
| 33FJ128MC506 || 4.97 || 40<br />
| 128 || 8 || 0<br />
| 53 || 16 || 8 || 8 || 8 || 9x16bit<br>4x32bit<br />
| 1 || 2 || 2 || 2 || 1 || 0<br />
|-<br />
| 33FJ128MC706 || 5.38 || 40<br />
| 128 || 16 || 0<br />
| 53 || 16 || 8 || 8 || 8 || 9x16bit<br>4x32bit<br />
| 1 || 2 || 2 || 2 || 1 || 0<br />
|-<br />
| 33FJ256GP506 || 6.11 || 40<br />
| 256 || 16 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 2 || 1 || 1<br />
|-<br />
|}<br />
<br />
===Web Page===<br />
*[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2529&param=en024856 Microchip Official Website]<br />
<br />
===Forum===<br />
*[http://direct.forum.microchip.com/default.aspx Microchip]: Official forum by Microchip<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=49 MPLAB ICD 2]: Subforum on ICD 2 programmer<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=57 MPLAB IDE]: Subforum on IDE<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=101 MPLAB C30 Compiler, ASM30, Link30 forum]: Subforum on C compiler. Refer to [http://ww1.microchip.com/downloads/en/DeviceDoc/C30_Users_Guide_51284e.pdf MPLAB C30 C Compiler User's Guide] Chapter 3<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=153 dsPIC30F Topics]: Subformum on dsPIC30F<br />
*[http://www.gnupic.org/ GNUPIC]: Discussion on PIC in Linux Systems<br />
**[http://www.linuxhacker.org/cgi-bin/ezmlm-cgi?1:dds:5443#b Debian]<br />
*[http://www.htsoft.com/forum/all/ubbthreads.php/Cat/0/C/6 HI-TECH Software Forum]: Discussion on dsPICC, a C compiler developed by HI-TECH<br />
*[http://piclist.com/techref/piclist/index.htm PICList]: Discussion on older PIC systems (not dsPIC)<br />
*[http://groups.google.com/group/pickit-devel PicKit]: Discussion on PICkit/PICkit 2 programmers<br />
*[http://sourceforge.net/forum/forum.php?forum_id=382005 FreeRTOS Real Time Kernel]: Open Discussion and Support on FreeRTOS <br />
<br />
===References===<br />
*dsPIC30F<br />
**[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2574 dsPIC30F Family Reference Manual Sections]: Contains detailed descriptions on dsPIC30F register definitions and example codes<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80169E.pdf dsPIC30F Family Reference Manual Errata (Use with revision 70046B only)]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70116F.pdf dsPIC30F5011, dsPIC30F5013 Data Sheet]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80210e.pdf dsPIC30F5011/5013 Rev. A1/A2 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80223D.pdf dsPIC30F5011/5013 Rev. A3 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70102G.pdf Flash Programming Specification]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70157B.pdf dsPIC30F Programmer's Reference Manual]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80170a.pdf dsPIC30F Programmer's Reference Manual Errata (use with revision DS70030E only)]<br />
<br />
*dsPIC33F<br />
**[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2573 dsPIC33F Family Reference Manual Sections]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70165E.pdf dsPIC33F Family Data Sheet]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80279B.pdf dsPIC33F Rev. A2 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80306A.pdf dsPIC33FJXXXGPX06/X08/X10 Rev. A2 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70152C.pdf Flash Programming Specification]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70172A.pdf dsPIC30F to dsPIC33F Conversion Guidelines]<br />
*ICD2 Programmer<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/51331B.pdf ICD2 User's Guide] <br />
*MPLAB<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/51519B.pdf MPLAB IDE User's Guide]<br />
*C30 Compiler<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/C30_Users_Guide_51284e.pdf MPLAB C30 C Compiler User's Guide]: Contains commands for using pic30-elf-gcc <br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/16bit_Language_Tool_Libraries_51456c.pdf 16-bit Language Tools Libraries]: Contains summaries and examples of using DSP libraries, standard C libraries and device libraries<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/Asm30_Link_Util_51317e.pdf MPLAB ASM30, MPLAB LINK30 and Utilities User's Guide]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/51322d.pdf dsPIC30F Language Tools Quick Reference Card]<br />
<br />
===Code Examples===<br />
*[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1408 Microchip Example Codes for dsPic]<br />
<br />
<br />
==Programming Methods==<br />
*There are 2 programming methods: In-Circuit Serial Programming (ICSP) and Run-Time Self-Programming (RTSP)<br />
*ICSP allows the devices to be programmed after being placed in a circuit board.<br />
*RTSP allows the devices to be programmed when an embedded program is already in operation.<br />
<br />
===ICSP: External Programmer (ICD2)===<br />
*Two types of ICSP are available: '''ICSP''' and '''Enhanced ICSP'''. Both of them require setting MCLR# to V<sub>IHH</sub> (9V – 13.25V).<br />
*Standard ICSP<br />
**Use external programmer (e.g. MPLAB<sup>®</sup> ICD 2, MPLAB<sup>®</sup> PM3 or PRO MATE<sup>®</sup> II) only.<br />
**Required low-level programming to erase, program and verify the chip.<br />
**Slower, because codes are serially executed.<br />
**Program memory can be erased using ''Normal-Voltage'' (4.5 – 5.5V) or ''Low-Voltage'' (2.5V – 4.5V).<br />
<br />
*Enhanced ICSP<br />
**Use external programmer and '''Programming Executive''' (PE).<br />
**PE is stored in the on-chip memory.<br />
**PE allows faster programming.<br />
**PE can be downloaded to the chip by external programmer using the standard ICSP method.<br />
**PE contains a small command set to erase, program and verify the chip, avoiding the need of low-level programming.<br />
<br />
====Hardware Interface====<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.1 Pin Used by ICSP<br />
! Pin Label !! Function !! Pin Number<br />
|- <br />
| MCLR# || Programming Enable|| 7<br />
|-<br />
| V<sub>DD</sub> || Power Supply || 10, 26, 38, 57<br />
|-<br />
| V<sub>SS</sub> || Ground || 9, 25, 41, 56<br />
|- <br />
| PGC || Serial Clock || 17<br />
|-<br />
| PGD || Serial Data || 18<br />
|-<br />
|}<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.2 Available Programmers in the Market<br />
! Product Name<br />
! Interface with PC<br />
! Interface with Device<br />
! Price (US)<br />
! Postage (US)<br />
! Total (US)<br />
|- <br />
| [http://direct.www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en010046&part=DV164005 MPLAB<sup>®</sup> ICD 2]<br />
| USB or RS232<br />
| [http://www.microchip.com/Microchip.WWW.SecureSoftwareList/secsoftwaredownload.aspx?device=en010046&lang=en&ReturnURL=http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en010046&part=DV164005# 6-PIN RJ-12 connector]<br />
| $159.99<br />
| -<br />
| -<br />
|-<br />
| [http://www.etekronics.com/product_info.php?cPath=24&products_id=48 Full Speed USB Microchip ICD2<br> Debugger and Programmer]<br />
| USB<br />
| 6-PIN ICSP connector<br>6-PIN RJ-12 connector<br />
| $72.00<br />
| $12.00<br />
| $84.00<br />
|-<br />
| [http://www.etekronics.com/product_info.php?cPath=24&products_id=47 Mini Microchip Compatible ICD2<br> Debugger and Programmer]<br />
| RS232<br />
| 6-PIN ICSP connector<br>6-PIN RJ-12 connector<br />
| $45.00<br />
| $10.00<br />
| $55.00<br />
|-<br />
| [http://www.inexglobal.com/microcontroller.php ICDX30]<br />
| RS232<br />
| 6-pin RJ-11<br />
| $51.00<br />
| $47.46<br />
| $98.46<br />
|-<br />
| *[http://www.sure-electronics.net Clone Microchip ICD2] (Now Using)<br />
| USB<br />
| 6-pin flat cables<br />
| $30.00<br />
| $12.00<br />
| $42.00<br />
|-<br />
|}<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.3 DIY ICD 2 Programmer Circuit<br />
! Source !! Schematic !! PIC16F877A Bootloader<br />
|- <br />
| [http://membres.lycos.fr/silicium31/Electronique/PIC/FreeIcdEnglish.htm Patrick Touzet]<br />
| [http://membres.lycos.fr/silicium31/Electronique/PIC/ICD2%20V1.3.pdf Yes]<br />
| [http://membres.lycos.fr/silicium31/Electronique/PIC/ICD2_FW.zip HEX]<br />
|-<br />
| [http://www.nebadje.org/doku.php?id=neblab:icd2clone Nebadje]<br />
| [http://people.ee.ethz.ch/~jbiveron/nebadje/ICD2_DOC.pdf Yes]<br />
| [http://people.ee.ethz.ch/~jbiveron/nebadje/ICD2_FW.zip Zip]<br />
|-<br />
|}<br />
<br />
====Software Interface====<br />
*The program can be written and compiled in an Integrated Development Environment (IDE) using either Assembly or C. The complied codes are then loaded to the device through the external programmer.<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.4 Summary of IDE<br />
! Product Name !! Features !! OS !! Price (US$)<br />
|- <br />
| [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en019469&part=SW007002 MPLAB<sup>®</sup> IDE]<br />
| Assembler Only<br />
| Windows<br />
| Free<br />
|-<br />
| [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en010065&part=SW006012 MPLAB<sup>®</sup> C30]<br />
| Assembler and C-Compiler<br />
| Windows<br />
| $895.00 (Free student version<sup>1</sup>)<br />
|-<br />
| [http://linux.softpedia.com/get/Science-and-Engineering/Electronic-Design-Automation-EDA-/Piklab-8099.shtml Piklab 0.12.0]<br />
| Assembler and C-Compiler<br />
| Linux<br />
| Free<sup>2</sup><br />
|}<br />
# Full-featured for the first 60 days. After 60 days, some code optimization functions are disabled. The compiler will continue to function after 60 days, but code size may increase.<br />
# The current version supports external programmer ICD 2, but not yet tested.<br />
<br />
===RTSP: COM Port (Bootloader)===<br />
*RTSP works in normal voltage (MCLR# no need to raise to V<sub>IHH</sub>).<br />
*No literature has mentioned the incorporation of Programming Executive (PE). Presumably, since Enhanced ICSP needs to set MCLR# to V<sub>IHH</sub>, RTSP cannot use PE.<br />
*Refer to [http://www.opencircuits.com/DsPIC30F_5011_Development_Board#Bootloader_Development bootloader section].<br />
<br />
<br />
==IC Requirements==<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 3.1 IC Requirements<br />
! Part No. !! Description <br />
! Min Temp !! Max Temp !! Min Volt !! Max Volt !! Typ Cur !! Max Cur<br />
|-valign="top"<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/70116F.pdf dsPIC30F5011-30I/PT] || uP <br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 2.5V <sup>[1]</sup>|| 5.5V<br />
| 145mA || 217mA<br />
|-<br />
| [http://datasheets.maxim-ic.com/en/ds/MAX3222-MAX3241.pdf MAX3232ESE] || RS232 driver<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 3.0V || 5.5V<br />
| 0.3mA || 1.0mA<br />
|-<br />
| [http://www.national.com/ds.cgi/DS/DS3695.pdf DS3695N] || RS485 driver<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 4.75V || 5.25V<br />
| 42mA || 60mA<br />
|-<br />
| [http://focus.ti.com/lit/ds/symlink/dac6574.pdf DAC6574IDGS] || 10-bit Quad-DAC I<sup>2</sup>C<br />
| -40<sup>o</sup>C || 105<sup>o</sup>C<br />
| 2.7V || 5.5V<br />
| 0.6mA || 0.9mA<br />
|-<br />
| [http://www.semiconductors.philips.com/acrobat/datasheets/74HC_HCT14_3.pdf 74HC14D] || Quad-Schmitt Trigger<br />
| -40<sup>o</sup>C || 125<sup>o</sup>C<br />
| 2.0V || 6.0V<br />
| || 0.02mA<br />
|-<br />
| '''Overall''' || <br />
| '''-40<sup>o</sup>C''' || '''85<sup>o</sup>C'''<br />
| '''4.75V''' || '''5.25V'''<br />
| || '''<300mA <sup>[2]</sup>'''<br />
|-<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/70165E.pdf dsPIC33FJ128GP306-I/PT] || uP <br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 3.0V <sup>[1]</sup>|| 3.6V<br />
| 74mA || 250mA<br />
|-<br />
| [http://www.analog.com/UploadedFiles/Data_Sheets/ADM3485E.pdf ADM3485EARZ] || RS485 driver<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 3.0V || 3.6V<br />
| 1.1mA || 2.2mA<br />
|-<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/21203N.pdf 24LC256-I/SN] || 256kBits I2C EEPROM<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 2.5V || 5.5V<br />
| 400uA || 3mA<br />
|-<br />
| [http://www.national.com/ds.cgi/LM/LM3940.pdf LM3940IMP-3.3] || 5V-3.3V Regulator<br />
| -40<sup>o</sup>C || 125<sup>o</sup>C<br />
| 5.0V || 7.5V<br />
| 10mA || 250mA<br />
|-<br />
|}<br />
#Minimum voltage measured is 3.3V (with 2 LEDs blinking) running at 30MHz.<br />
#Measured current at 5V is 180mA (with 2 LEDs blinking only)<br />
<br />
<br />
==Development Environment==<br />
<br />
===Windows===<br />
<br />
[[Image:PIC_setup_win.JPG]]<br />
<br />
*C-Compiler, Assembler and Linker are under GNU license.<br />
**MPLAB C30 C Compiler (*.c -> *.s)<br />
**MPLAB ASM30 Assembler (*.s -> *.o)<br />
**MPLAB LINK30 Linker (*.o -> *.bin)<br />
<br />
*PA optimizer, simulator, runtime libraries, header files, include files, and linker scripts are not covered by GNU. Reference is [http://direct.forum.microchip.com/tm.aspx?m=107208 here].<br />
<br />
*Microchip has integrated ASM30, LINK30, assembly header files, linker scripts in MPLAB IDE, which is free for download.<br />
*MPLAB C30 costs US$895. A 60-day free student version is also available. After 60-days, the optimizer is automatically disabled, while other tools can still function properly. Refer to Table 2.4.<br />
<br />
*C-libraries contained in C30 includes (Refer to [http://ww1.microchip.com/downloads/en/DeviceDoc/16bit_Language_Tool_Libraries_51456c.pdf 16-Bit Language Tools Libraries] from Microchip).<br />
<br />
<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 4.1 C Libraries in MPLAB C30<br />
! Library !! Directory <br>(\\Microchip\MPLAB C30) !! Major functions<br />
|-valign="top"<br />
| DSP Library <br>(e.g. libdsp-coff.a)<br />
| \lib <br> \src\dsp <br> \support\h<br />
| Vector, Matrix, Filter, etc.<br />
|-valign="top"<br />
| 16-Bit Peripheral Libraries <br>(e.g. libp30F5011-coff.a)<br />
| \lib <br> \src\peripheral <br> \support\h<br />
| ADC12, IOPort, UART, I<sup>2</sup>C, etc.<br />
|-valign="top"<br />
| Standard C Libraries <br>(e.g. libc-coff.a, libm-coff.a, libpic-coff.a)<br />
| \lib <br> \src\libm <br> \include<br />
| stdio.h, time.h, float.h, math.h, <br />
|-valign="top"<br />
| MPLAB C30 Built-in Functions<br />
| none<br />
| _buildin_addab, _buildin_add, _buildinmpy, etc<br />
|-<br />
|}<br />
<br />
===Linux===<br />
<br />
[[Image:PIC_setup_linux.JPG]]<br />
<br />
*C Compiler, Assembler and Linker are under GNU license.<br />
**The code can be downloaded from Microchip at [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en023073 here].<br />
**Current MPLAB ASM30 Assembler: v2.04<br />
**Current MPLAB C30 Compiler: v2.04<br />
<br />
*[http://gcc.gnu.org/ml/gcc/2005-02/msg01144.html John Steele Scott] has made templates that can be readily used by Debian-based systems. <br />
*For v1.32, the necessary conversion to *.deb has been done already at [http://noel.feld.cvut.cz/dspic/ here].<br />
**Download '''pic30-1.32-debian.tar.bz2''' for Template v1.32.<br />
**Download '''pic30-binutils_1.32-1_i386.deb''' for the assember.<br />
**Download '''pic30-gcc_1.32-1_i386.deb''' for the compiler.<br />
*For v2.00<br />
**goto http://www.baycom.org/~tom/dspic/<br />
**download pic30-gcc-2.00-1.i386.rpm and pic30-binutils-2.00-1.i386.rpm<br />
**convert to deb files<br />
**install these two deb files<br />
*For v3.01, convert the Toolchain following instructions at [http://www.nabble.com/Debian-templates-for-dsPIC-build-toolchain-3.01-tf4308624.html here]<br />
**pre-install these packages: dpkg-dev, debhelper, bison, flex, sysutils, gcc-3.3, fakeroot<br />
**pack pic30-binutils into deb file<br />
**install pic30-binutils<br />
**pack pic30-gcc-3.01 into deb file<br />
**install pic30-gcc-3.01<br />
**pack pic30-support into deb file<br />
**install pic30-support<br />
*'''Important Note''': Only the compiler is free. The header files and library are owned by Microchip. <br />
**Thomas Sailer suggested to download the Student version of C30 compiler and then build the libraries without source code. A package template for Fedora system is available [http://www.baycom.org/~tom/dspic/ here].<br />
**Instructions for filling the upstream direction is available [http://forum.microchip.com/printable.aspx?m=139360 here].<br />
**Alteratively, [https://gna.org/projects/pic30-libc/ Stephan Walter] has started a project to develop C Runtime Library for dsPIC. <br />
***Current libraries in version 0.1.1 include: assert.h, cdefs.h, ctype.h, errno.h, inttypes.h, stdint.h, stdio.h, stdlib.h, string.h<br />
<br />
*Burning Program Codes to Target Board<br />
#Use 'dspicprg and dspicdmp' utilities developed by [http://homerreid.ath.cx/misc/dspicprg/ Homer Reid] to burn hex code (*.hex) to devices. See Reference [http://forum.microchip.com/tm.aspx?m=94243 here]. Through serial port only?<br />
#Use [http://piklab.sourceforge.net/ Piklab IDE]. Details on file format not known.<br />
#Use [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en019469&part=SW007002 MPLAB IDE] to burn hex code (*.hex) to devices.<br />
<br />
===Code Optimization===<br />
*Below is a comparsion between different optimization levels for the project including drivers for 2 projects.<br />
<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 4.2 Comparison between differnt optimization levels<br />
! Optimization !! Description !! Project 1<br>Code Size<br>(byte) !! Project 1<br>Data Usage<br>(byte) !! Project 2<br>Code Size<br>(byte) !! Project 2<br>Data Usage<br>(byte)<br />
|-valign="top"<br />
| O0 <br />
| No optimization<br>Fastest Compilation<br />
| 6222 (9%) || 178 (4%) || 26,037 (38%) || 710 (17%)<br />
|-valign="top"<br />
| O1 <br />
| Optimize<br> Tries to reduce code size and execution time.<br />
| 4473 (6%) || 178 (4%) || 22,290 (32%) || 710 (17%)<br />
|-valign="top"<br />
| O2 <br />
| Optimize even more<br> Performs nearly all supported optimizations <br>that do not involve a space-speed trade-off. <br>Increases both compilation time and the <br>performance of the generated code.<br />
| 4422 (6%) || 178 (4%) || 21,993 (32%) || 710 (17%)<br />
|-valign="top"<br />
| O3 <br />
| Optimize yet more. <br>O3 turns on all optimizations specified by O2 <br>and also turns on the inline-functions option.<br />
| 4485 (6%) || 178 (4%) || 22,176 (32%) || 710 (17%)<br />
|-valign="top"<br />
| Os <br />
| Optimize for size. <br>Os enables all O2 optimizations that do not <br>typically increase code size. It also performs <br>further optimizations designed to reduce code <br>size.<br />
| 4356 (6%) || 178 (4%) || 21,885 (32%) || 710 (17%)<br />
|-<br />
|}<br />
<br />
<br />
==Software Architecture==<br />
+--------+--------+--------+--------+--------+<br />
Application | Task 1 | Task 2 | Task 3 | Task 4 | Task 5 |<br />
+--------+--------+--------+--------+--------+<br />
| POSIX API |<br />
+-------------------+------------------------+<br />
OS | Coroutine | FreeRTOS Scheduler |<br />
+-------------------+------------------------+<br />
| Drivers |<br />
+------+-----+-----+--------+-------+--------+<br />
Hardware | UART | ADC | DAC | EEPROM | PWM | TIMERS | <br />
+------+-----+-----+--------+-------+--------+<br />
*Currently, operating system is based on [http://www.freertos.org/ FreeRTOS] incorporating coroutine developed by [http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html Simon Tatham]<br />
*Software Drivers are to be developed to allow users at Application Level to use the hardware (e.g. ADC, DAC, UART, EEPROM etc) through the OS.<br />
*The interface between the drivers and the OS is based on [http://www.die.net/doc/linux/man/man2/ POSIX standard] (e.g. open(), write(), read(), ioctl(), usleep() etc).<br />
*The most up-to-date development can be found at repository [http://chungyan5.no-ip.org/vc/?root=freertos_posix freertos_posix]<br />
<br />
<br />
==Programming Tips==<br />
<br />
===Memory Map for 5011===<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 6.1 Memory Location<br />
! Type !! Start Address !! End Address !! Size<br />
|-valign="top"<br />
| Flash || 0x000000 ||0x00AFFF || 44K<sup>[1]</sup><br />
|-valign="top"<br />
| +--Flash: Reset Vector || 0x000000 ||0x000003 || 4<br />
|-valign="top"<br />
| +--Flash: Interrupt Vector Table || 0x000004 ||0x00007F || 124<br />
|-valign="top"<br />
| +--Flash: Alternate Vector Table || 0x000084 ||0x0000FF || 124<br />
|-valign="top"<br />
| +--Flash: User Program || 0x000100 ||0x00AFFF || 43.7K<br />
|-valign="top"<br />
| EEPROM || 0x7FFC00 || 0x7FFFFF || 1K<sup>[2]</sup><br />
|-valign="top"<br />
| Programming Executive || 0x800000 || 0x8005BF || 1472<br />
|-valign="top"<br />
| Unit ID || 0x8005C0 || 0x8005FF || 64<br />
|-valign="top"<br />
| Config Registers || 0xF80000 || 0xF8000F || 16<br />
|-valign="top"<br />
| Device ID || 0xFF0000 || 0xFF0003 || 4<br />
|-<br />
|}<br />
[1] Each address is 16-bit wide. Every two addresses correspond to a 24-bit instruction. Each even address contains 2 valid bytes; each odd address contains 1 valid byte plus 1 phathom byte.<br><br />
[2] Each address is 8-bit wide.<br />
<br />
===Data Location===<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 6.2 Data Location<br />
! Type !! Description !! Example<br />
|-valign="top"<br />
| _XBSS(N) <sup>[1]</sup><br />
| RAM Data in X-memory, aligned at N, no initilization<br />
| int _XBSS(32) xbuf[16];<br />
|-valign="top"<br />
| _XDATA(N) <sup>[1]</sup><br />
| RAM Data in X-memory, aligned at N, with initilization<br />
| int _XDATA(32) xbuf[] = {1, 2, 3, 4, 5};<br />
|-valign="top"<br />
| _YBSS(N) <sup>[1]</sup><br />
| RAM Data in Y-memory, aligned at N, no initilization<br />
| int _YBSS(32) ybuf[16];<br />
|-valign="top"<br />
| _YDATA(N) <sup>[1]</sup><br />
| RAM Data in Y-memory, aligned at N, with initilization<br />
| int _YDATA(32) ybuf[16] = {1, 2, 3, 4, 5};<br />
|-valign="top"<br />
| __attribute__((space(const)))<br />
| Flash ROM data, constant, accessed by normal C<br>statements, but 32K max.<br />
| int i __attribute__((space(const))) = 10;<br />
|-valign="top"<br />
| __attribute__((space(prog)))<br />
| Flash ROM data, read/write by program space visibility<br>window (psv)<br />
| int i __attribute__((space(prog)));<br />
|-valign="top"<br />
| __attribute__((space(auto_psv)))<br />
| Flash ROM data, read by normal C statements, write<br>by accessing psv<br />
| int i __attribute__((space(auto_psv)));<br />
|-valign="top"<br />
| __attribute__((space(psv)))<br />
| Flash ROM data, read/write by (psv)<br />
| int i __attribute__((space(psv)));<br />
|-valign="top"<br />
| _EEDATA(N) <sup>[1]</sup><br />
| ROM Data in EEPROM, aligned at N, read/write with psv<br />
| int _EEDATA(2) table[]={0, 1, 2, 3, 5, 8};<br />
|-valign="top"<br />
| _PERSISTENT<br />
| RAM Data, data remain after reset<br />
| int _PERSISTENT var1, var2;<br />
|-valign="top"<br />
| _NEAR<br />
| RAM Data at near section<br />
| int _NEAR var1, var2;<br />
|-valign="top"<br />
| _ISR<br />
| Interrupt service rountine<br />
| void _ISR _INT0Interrupt(void);<br />
|-valign="top"<br />
| _ISRFAST<br />
| Fast interrupt service rountine<br />
| void _ISRFAST _T0Interrupt(void);<br />
|-<br />
|}<br />
#N must be a power of two, with a minimum value of 2.<br />
<br />
===Configuration Bits===<br />
----<br />
*System clock source can be provided by:<br />
#Primary oscillator (OSC1, OSC2)<br />
#Secondary oscillator (SOSCO and SOSCI) with 32kHz crystal<br />
#Internal Fast RC (FRC) oscillator at 7.37MHz (7372800Hz)<br />
#Low-Power RC (LPRC) oscillator (Watchdog Timer) at 512 kHz.<br />
*These clock sources can be incorporated with interal Phase-locked-loop (PLL) x4, x8 or x16 to yield the osciallator frequrence F<sub>OSC</sub><br />
*The system clock is divided by 4 to yield the internal instruction cycle clock, F<sub>CY</sub>=F<sub>OSC</sub>/4<br />
*FRC with PLLx16 is used to achieve F<sub>CY</sub>=29.49MHz (29491200Hz or 30MIPS)<br />
<br />
//The code (MACRO) below is to be placed at the top of program (before main)<br />
_FOSC(CSW_FSCM_OFF & FRC_PLL16);<br />
_FWDT(WDT_OFF); //Turn off Watchdog Timer<br />
_FBORPOR(PBOR_ON & BORV_27 & MCLR_DIS & PWRT_16);<br />
_FGS(CODE_PROT_OFF); //Disable Code Protection<br />
<br />
===Timer===<br />
<br />
----<br />
*Each timer is 16-bit (i.e. counting from 0 to 65535).<br />
*Timer 2 and 3 can be incorporated together to form a 32-bit timer.<br />
*Prescale is the ratio between timer counts and system clock counts. Prescales of 1:1, 1:8, 1:64 and 1:256 are available.<br />
*Timers may be used to implement free time clock or mesaure time.<br />
<br />
====Free Time Clock====<br />
*Let required time for ticking be PERIOD.<br />
*Number of instruction cycles during PERIOD = PERIOD*F<sub>CY</sub> cycles<br />
*Using a prescale of 1:x, the timer period count register = # of cycles/x<br />
*e.g. PERIOD = 10ms; # of cycles = 10ms*30MHz = 300000 cylces; Using 1:64 Prescale, register setting = 300000/64 = 4688<br />
void time_init(void){<br />
TMR1 = 0; // Clear register<br />
PR1 = 4688; // Set period<br />
//============================================================<br />
_T1IF = 0; // Clear interrupt flag<br />
_T1IE = 1; // Enable interrupts<br />
//============================================================<br />
T1CONbits.TCS = 0; // Use internal clock source<br />
T1CONbits.TCKPS = 2; // Prescale Select 1:64<br />
T1CONbits.TON = 1; // Start the timer <br />
}<br />
//********************************************************************<br />
void _ISRFAST _T1Interrupt(void){<br />
_T1IF = 0; // Clear interrupt flag<br />
//Place user code here<br />
}<br />
<br />
====Time Measurement====<br />
*To measure the time taken for action(), use the code below:<br />
unsigned int measure_time(void){ <br />
PR3 = 0xFFFF; // Set counter to maximum<br />
_T3IF = 0; // Clear interrupt flag<br />
_T3IE = 0; // Disable interrupt<br />
T3CONbits.TON = 1; // Start the timer, TMR3 count up<br />
TMR3 = 0; //Clear TMR3 to start count up<br />
//====================================================<br />
//Add code here to wait for something to happen<br />
action();<br />
//====================================================<br />
T3CONbits.TON = 0; //Stop the timer<br />
//====================================================<br />
return (unsigned int) TMR3/FCY; //TMR/FCY yields the actual time<br />
}<br />
<br />
===Interrupt===<br />
<br />
----<br />
*Registers are involved in Interrupts includes: <br />
#Interrupt Flag Status (IFS0-IFS2) registers<br />
#Interrupt Enable Control (IEC0-IEC2) registers<br />
#Interrupt Priority Control (IPC0-IPC10) registers<br />
#Interrupt Priority Level (IPL) register<br />
#Global Interrupt Control (INTCON1, INTCON2) registers<br />
#Interrupt vector (INTTREG) register<br />
*User may assign priority level 0-7 to a specific interrupt using IPC. Setting priority to 0 disable a specific interrupt. Level 7 interrupt has the highest priority.<br />
*Current priority level is stored in bit<7:5> of Status Register (SR). Setting Interrupt Priority Level (IPL) to 7 disables all interrupts (except traps). <br />
*sti() and cli() can be defined to enable and disable global interrupts for time critical functions:<br />
#define IPL ( 0x00e0 )<br />
#define cli() SR |= IPL //Set IPL to 7<br />
#define sti() SR &= ~IPL //Set IPL to 0<br />
//============================================================<br />
char adc_ioctl(unsigned char request, unsigned char* argp){<br />
//...<br />
cli(); //Disable global interrupt<br />
for(;ch<=argp[0];ch++)<br />
adc_add_ch(argp[ch]); //Add adc channels<br />
sti(); //Enable global interrupt<br />
//...<br />
return 0;<br />
}<br />
*dsPic30F has an [http://ww1.microchip.com/downloads/en/DeviceDoc/80223D.pdf errate note] on the Interrupt Controller. When Nested Interrupt is turned on (NSTDIS=0 by default), a high priority interrupt negating a low priority interrupt may result in an Address Error.<br />
*To work around the problem, it is suggested by Microchip to use the following MACRO to protect:<br />
# the clearing of Interrput Flag<br />
# the disabling of Interrupt Enable<br />
# the lowering of Interrupt Priority <br />
# the modification of IPL in Status Register to 1-6<br />
#define DISI_PROTECT(X) { \<br />
__asm__ volatile ("DISI #0x1FFF");\<br />
X; \<br />
DISICNT = 0; \<br />
}<br />
*For example,<br />
void _ISR _T1Interrupt( void )<br />
{<br />
DISI_PROTECT(IFS0bits.T1IF = 0);<br />
//do something here...<br />
}<br />
<br />
===UART===<br />
<br />
----<br />
*5011 provides two UART channels UxART, for x=1, 2.<br />
*UxMODE, UxSTA, UxBRG are registers used to set the mode, indicate the status, and set the baud rate respectively.<br />
*For UART communications compatiable with RS232 standard, an external driver (e.g. MAX3232ESE) is needed.<br />
*For UART communications compatiable with RS485 standard, an external driver (e.g. DS3695N) is needed.<br />
====Auto baud rate detection====<br />
*The method is provided by [http://www.opencircuits.com/DsPIC30F_5011_Development_Board ingenia bootloader].<br />
*The PC sends a ASCII character 'U' (0x55) to the target board.<br />
*On the first rising edge of the start bit, the target board starts the timer.<br />
*At the fifth rising edge, the timer is stopped, let the count number be ''t_count''. <br />
**The measured period corresponds to 8 bits transmitted at a baud rate ''uxbrg''.<br />
_ _ _ _ _ _<br />
_|S|_|1|_|1|_|1|_|1|_|S|_ (S = Start Bit)<br />
<---------------><br />
Measured Time<br />
*The relationship between ''uxbrg'' and ''TMR'' is<br />
Measured Time (in seconds) = t_count/F<sub>cy</sub><br />
uxbrg = 1/(Measured Time/8)<br />
= 8*F<sub>cy</sub>/t_count<br />
*Since UxBRG is computed by:<br />
UxBRG = (F<sub>cy</sub>/(16*Baudrate)) -1<br />
= (F<sub>cy</sub>/(16*8*F<sub>cy</sub>/t_count)) -1<br />
= t_count/128 -1<br />
*The following is the code for auto baud rate detection for U2ART:<br />
unsigned int uart2_autobaud(void){<br />
U2MODEbits.ABAUD = 1; //Enable Autobaud detect from U2RX (from IC2 if 0)<br />
U2MODEbits.UARTEN = 1; //U2ART enable<br />
//Timer 3 Config==========================================================<br />
PR3 = 0xFFFF; // Set counter to maximum<br />
_T3IF = 0; // Clear interrupt flag<br />
_T3IE = 0; // Disable interrupt<br />
T3CONbits.TON = 1; // Start the timer, TMR3 count up<br />
//Input Capture Config====================================================<br />
IC2CONbits.ICM = 3; //Detect rising <br />
_IC2IF = 0; //Clear interrupt flag<br />
_IC2IE = 0; //Disable interrupt<br />
//Start Auto baud detection===============================================<br />
unsigned int i=0;<br />
cli(); //Disable Global Interrupt<br />
while(!_IC2IF); //1st rising edge detected<br />
TMR3 = 0; //Clear TMR3 to start count up<br />
_IC2IF = 0; //Clear interrupt flag<br />
while(!_IC2IF); //2nd rising edge detected<br />
_IC2IF = 0; //Clear interrupt flag<br />
while(!_IC2IF); //3rd rising edge detected<br />
_IC2IF = 0; //Clear interrupt flag<br />
while(!_IC2IF); //4th rising edge detected<br />
_IC2IF = 0; //Clear interrupt flag<br />
while(!_IC2IF); //5th rising edge detected<br />
_IC2IF = 0; //Clear interrupt flag<br />
T3CONbits.TON = 0; //Stop the timer<br />
sti(); //Enable Global Interrupt<br />
//Compute value for BRG register==========================================<br />
unsigned int time;<br />
time = ((TMR3+0x40)>>7)-1; //+0x40 for rounding<br />
//========================================================================<br />
return time;<br />
}<br />
*For 30MIP, tested speeds of transmission include 9600bps, 19200bps, 28800bps, 38400bps and 57600bps.<br />
====open()====<br />
*The following structures and variables are used as circular buffers for transmit and receive.<br />
struct UART_Rx{<br />
unsigned char wr;<br />
unsigned char rd;<br />
};<br />
struct UART_Tx{<br />
unsigned char wr; <br />
unsigned char rd;<br />
unsigned char tx_complete_flag;<br />
};<br />
struct UART_Rx uart_rx;<br />
struct UART_Tx uart_tx;<br />
unsigned char uart_rx_buf[MAX_UART_RX_BUF];<br />
unsigned char uart_tx_buf[MAX_UART_TX_BUF];<br />
<br />
char uart_open()<br />
{<br />
uart_rx.wr = 0;<br />
uart_rx.rd = 0;<br />
uart_tx.wr = 0;<br />
uart_tx.rd = 0;<br />
uart_tx.tx_complete_flag = 1;<br />
uart2_init();<br />
return 0;<br />
}<br />
<br />
void uart2_init(void){<br />
unsigned int u2brg = 97; <br />
#if(AUTO_BAUD_DECT>0)<br />
u2brg = uart2_autobaud();<br />
#endif<br />
U2BRG = u2brg; <br />
//=================================================================<br />
// Disable U2ART<br />
U2MODEbits.UARTEN = 0; //Disable U2ART module<br />
//=================================================================<br />
// Configure Interrupt Priority<br />
_U2RXIF = 0; //Clear Rx interrupt flags<br />
_U2TXIF = 0; //Clear Tx interrupt flags<br />
_U2RXIE = 1; //Receive interrupt: 0 disable, 1 enable <br />
_U2TXIE = 1; //Transmit interrupt: 0 disable, 1 enable<br />
//=================================================================<br />
// Configure Mode<br />
// +--Default: 8N1, no loopback, no wake in sleep mode, continue in idle mode<br />
// +--Diable autobaud detect<br />
// +--Enable U2ART module<br />
U2MODEbits.ABAUD = 0; //Disable Autobaud detect from U2RX <br />
U2MODEbits.UARTEN = 1; //U2ART enable<br />
//=================================================================<br />
// Configure Status<br />
// +--Default: TxInt when a char is transmitted, no break char<br />
// +--Default: RxInt when a char is received, no address detect, clear overflow<br />
// +--Enable Transmit<br />
U2STAbits.UTXEN = 1; //Tx enable<br />
}<br />
<br />
====write()====<br />
*This function writes a series of bytes to the circular buffer and start transmission.<br />
int uart_write(unsigned char *buf, int count)<br />
{<br />
//If transimt has not completed, return busy<br />
if(uart_tx.tx_complete_flag == 0){<br />
return -1; <br />
}<br />
else{<br />
uart_tx.tx_complete_flag = 0;<br />
}<br />
int next_data_pos;<br />
int byte = 0;<br />
for (; byte<count; byte++) {<br />
next_data_pos = pre_wr_cir254buf( (unsigned char)uart_tx.wr, <br />
(unsigned char)uart_tx.rd, <br />
MAX_UART_TX_BUF); <br />
if (next_data_pos!=255) {<br />
//Valid data is available<br />
uart_tx_buf[uart_tx.wr] = (unsigned char) buf[byte]; //copy the char to tx_buf<br />
uart_tx.wr = next_data_pos; //increment the ptr<br />
} else break;<br />
}<br />
//Raise Interrupt flag to initiate transmission<br />
_U2TXIF = 1; //Start interrupt<br />
return byte; <br />
}<br />
*The interrupt routine reads from the circular buffer and send the data. The uart is opened such that the module will generate an TX Interrupt when it a byte is sent.<br />
void _ISR _U2TXInterrupt(void){<br />
DISI_PROTECT(_U2TXIF = 0); //Clear Interrupt Flag<br />
unsigned char next_data_pos;<br />
next_data_pos = pre_rd_cir254buf( (unsigned char)uart_tx.wr,<br />
(unsigned char)uart_tx.rd, <br />
MAX_UART_TX_BUF);<br />
if (next_data_pos!= 255) {<br />
//Valid Data is available to transmit<br />
U2TXREG = (uart_tx_buf[(unsigned char)uart_tx.rd] & 0xFF); //send next byte...<br />
uart_tx.rd = (unsigned char) next_data_pos; //update rd pointer<br />
} else {<br />
//Transimission has completed<br />
uart_tx.tx_complete_flag = 1; // change to empty of tx<br />
}<br />
}<br />
<br />
====read()====<br />
*The interrupt routine writes to the circular buffer when space is available.<br />
void _ISR _U2RXInterrupt(void){<br />
unsigned char next_data_pos;<br />
if ( U2STAbits.URXDA ){<br />
next_data_pos = pre_wr_cir254buf( uart_rx.wr, uart_rx.rd, MAX_UART_RX_BUF);<br />
if (next_data_pos!=255) {<br />
//If buffer is not full<br />
uart_rx_buf[uart_rx.wr] = (unsigned char) U2RXREG; //Read the data from buffer<br />
uart_rx.wr = next_data_pos;<br />
} <br />
else{<br />
//When buffer is full, still remove data from register, butthe incoming data is lost<br />
next_data_pos = (unsigned char) U2RXREG; //Read the data from buffer<br />
} <br />
}<br />
DISI_PROTECT(_U2RXIF = 0); //Clear the flag<br />
}<br />
*This function reads one byte from the circular buffer.<br />
int uart_read(unsigned char *buf)<br />
{<br />
int next_data_pos;<br />
next_data_pos = pre_rd_cir254buf( uart_rx.wr, uart_rx.rd, MAX_UART_RX_BUF);<br />
//Copy 1 byte when data is available<br />
if (next_data_pos!=255) <br />
{<br />
*buf = uart_rx_buf[uart_rx.rd]; //copy the stored data to buf<br />
uart_rx.rd = next_data_pos; //update the ptr<br />
return 1;<br />
}<br />
//No data can be copied<br />
else<br />
{<br />
return 0;<br />
} <br />
}<br />
<br />
===I<sup>2</sup>C===<br />
<br />
----<br />
*Two lines are devoted for the serial communication. SCL for clock, SDA for data.<br />
*Standard communication speed includes<br />
#Standard speed mode: 100kHz<br />
#Fast speed mode: 400kHz<br />
#High speed mode: 3.4MHz<br />
*dsPIC30f5011 supports standard and fast speed modes. The maximum speed attainable is 1MHz.<br />
*Pull-up resistors are required for both SCL and SDA. Minimum pull-up resistance is given by:<br />
Pull-up resistor (min) = (V<sub>dd</sub>-0.4)/0.003 ...... [See section 21.8 in Family reference manual]<br />
*2.2Kohm is typical for standard speed mode.<br />
*After initiating a start/stop/restart bit, add a small delay (e.g. no operation) before polling the corresponding control bit (hardware controlled).<br />
*After sending a byte and receiving an acknowledgement from the slave device, ensure to change to idle state.<br />
<br />
====open()====<br />
*The following structure is used to record whether special bits are needed to be sent.<br />
typedef union{<br />
unsigned char val;<br />
struct{<br />
unsigned START:1; //start<br />
unsigned RESTART:1; //restart<br />
unsigned STOP:1; //stop<br />
unsigned NACK:1; //not acknowledgment<br />
unsigned :1;<br />
unsigned :1;<br />
unsigned :1;<br />
unsigned :1; <br />
}bits;<br />
} I2C_STATUS;<br />
static I2C_STATUS i2c_status; <br />
<br />
*Initializing I<sup>2</sup>C with default speed I2C_BRG without interrupts.<br />
void i2c_open(void)<br />
{<br />
//Open i2c if not already opened<br />
if(I2CCONbits.I2CEN == 0)<br />
{<br />
_SI2CIF = 0; //Clear Slave interrupt<br />
_MI2CIF = 0; //Clear Master interrupt<br />
_SI2CIE = 0; //Disable Slave interrupt<br />
_MI2CIE = 0; //Disable Master interrupt<br />
I2CBRG = I2C_BRG;<br />
I2CCONbits.I2CEN = 1; //Enable I2C module <br />
i2cIdle(); //I2C bus at idle state, awaiting transimission<br />
i2c_status.val = 0; //clear status flags<br />
}<br />
}<br />
<br />
====ioctl()====<br />
*Use this function before read/write to append special bits before or after the data byte.<br />
char i2c_ioctl(unsigned char request, unsigned char* argp)<br />
{<br />
switch(request){<br />
case I2C_SET_STATUS:<br />
i2c_status.val = *argp;<br />
break;<br />
default:<br />
return -1; //request code not recognised <br />
}<br />
return 0;<br />
}<br />
<br />
====write()====<br />
*This function sends an 8-bit data using the I2C protocol.<br />
Mst/Slv _______ M ____M___ S M ________ <br />
SDA (Data) |S| data |A|S|<br />
|T| |C|T|<br />
|A|XXXXXXXX|K|P|<br />
*Use ioctl() to select whether a start/restart/stop bit is required.<br />
*If slave does not respond after ACK_TIMEOUT, the transmission is considered unsucessful.<br />
int i2c_write(unsigned char *buf)<br />
{<br />
unsigned int count = 0;<br />
if(i2c_status.bits.START)<br />
{<br />
I2CCONbits.SEN = 1; <br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.SEN); //Wait till Start sequence is completed<br />
}<br />
else if(i2c_status.bits.RESTART)<br />
{<br />
I2CCONbits.RSEN = 1; <br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.RSEN); //Wait till Start sequence is completed<br />
}<br />
I2CTRN = *buf; //Transmit register<br />
while(I2CSTATbits.TBF); //Wait for transmit buffer to empty<br />
while(I2CSTATbits.ACKSTAT){<br />
if(++count > ACK_TIMEOUT){<br />
//Slave did not acknowledge, byte did not transmit sucessfully, <br />
//send stop bit to reset i2c<br />
I2CCONbits.PEN = 1;<br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.PEN); //Wait till stop sequence is completed<br />
i2cIdle();<br />
return 0;<br />
}<br />
}<br />
i2cIdle();<br />
if(i2c_status.bits.STOP)<br />
{<br />
I2CCONbits.PEN = 1;<br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.PEN); //Wait till stop sequence is completed<br />
i2cIdle();<br />
}<br />
i2c_status.val = 0; //Clear status<br />
return 1;<br />
}<br />
<br />
====read()====<br />
*This function reads 1 byte from slave using the I2C protocol.<br />
Mst/Slv ____ ___S____ M M _____ <br />
SDA (Data) | data |A|S|<br />
| |C|T|<br />
|XXXXXXXX|K|P|<br />
*Use ioctl() to select whether an ACK/NACK and/or STOP bit is needed to be sent.<br />
int i2c_read(unsigned char *buf)<br />
{<br />
I2CCONbits.RCEN = 1; //Enable Receive<br />
while(I2CCONbits.RCEN);<br />
I2CSTATbits.I2COV = 0; //Clear receive overflow<br />
*buf = (unsigned char) I2CRCV; //Access the receive buffer<br />
I2CCONbits.ACKDT = (i2c_status.bits.NACK)? 1 : 0;<br />
I2CCONbits.ACKEN = 1; //Send Acknowledgement/Not Acknowledgement<br />
i2cIdle(); //I2C bus at idle state, awaiting transimission<br />
if(i2c_status.bits.STOP)<br />
{<br />
I2CCONbits.PEN = 1;<br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.PEN); //Wait till stop sequence is completed<br />
i2cIdle();<br />
}<br />
i2c_status.val = 0; //Clear status<br />
return 1;<br />
}<br />
<br />
====Example====<br />
Mst/Slv _______ M ___M___ M S ____M___ S M ___M___ M S ___S____ M ___S____ M M _____ <br />
SDA (Data) |S| | |A| |A|R| | |A| |A| |N|S|<br />
|T|address|W|C|channelA|C|E|address|R|C| Data H |C| Data L |A|T|<br />
|A|1001111|0|K|00010010|K|S|1001111|1|K|10101010|K|10XXXXXX|K|P|<br />
<br />
/*<br />
* Send start bit, slave address (Write Mode)<br />
*/ <br />
status = I2C_START;<br />
i2c_ioctl(I2C_SET_STATUS, &status);<br />
data = (unsigned char) I2C_SLAVE_ADDR;<br />
i2c_write(&data);<br />
/*<br />
* Send control byte: Channel select<br />
*/<br />
data = (unsigned char) ctrl_byte;<br />
i2c_write(&data);<br />
/*<br />
* Send restart bit, slave address (Read Mode)<br />
*/<br />
status = I2C_RESTART;<br />
i2c_ioctl(I2C_SET_STATUS, &status);<br />
data = (unsigned char) (I2C_SLAVE_ADDR|0x01);<br />
i2c_write(&data);<br />
/*<br />
* Receive High Byte with Acknowledgment<br />
*/<br />
i2c_read(&data);<br />
usr_data.high = (unsigned char) data;<br />
/*<br />
* Receive Low Byte with Not Acknowledgment and stop bit<br />
*/ <br />
status = I2C_NACK | I2C_STOP;<br />
i2c_ioctl(I2C_SET_STATUS, &status);<br />
i2c_read(&data);<br />
usr_data.low = (unsigned char) data;<br />
<br />
===ADC===<br />
<br />
----<br />
*12-bit ADC: (Max 16 Channels)<br />
*Allow a maximum of 2 sets of analog input multiplexer configurations, MUX A and MUX B (Normally use one only).<br />
*A maximum of 200kps of sampling rate when using auto sampling mode.<br />
====open()====<br />
*The following variables are required.<br />
unsigned int adc_buf[ADC_MAX_CH]; //Store most updated data<br />
volatile unsigned int* ADC16Ptr = &ADCBUF0; //Pointer to ADC register buffer, <br />
unsigned char adc_ch_select = 0; //Pointer to channel to be read from<br />
unsigned char adc_data_ready = 0; //Indicate if RAM data is ready for output<br />
*Configuration is highlighted below.<br />
**Interrupt: The ADC module will be set to interrupt when the specified channels are updated.<br />
**I/O: Set the corresponding TRISBX bits (digit i/o config) to input (i.e. = 1), and set corresponding bits in ADPCFG (analog config) to zero.<br />
**Scanning Mode: Scan mode is used. In this mode, the Sample and Hold (S/H) is switched between the channels specified by ADCSSL (Scan select register).<br />
**Reference Voltage for S/H: Only MUX A is used. By default, the negative reference voltage of the S/H is connected to V<sub>REF-</sub>.<br />
**Settings for ADC Operation: For 200kbps operation, the voltage references for the ADC voltage are connected to V<sub>REF+</sub> and V<sub>REF-</sub>. Scan input is enabled, and the module will generate an interrupt when all selected channels have been scanned.<br />
**Sampling Rate: T<sub>AD</sub> refers to the time unit for the ADC clock. To configure the ADC module at 200kbps, the minimum sampling time of 1T<sub>AD</sub> = 334ns is required. ADCS<5:0> in ADCON3 register is used to set the time, which is given by:<br />
ADCS<5:0> = 2(T<sub>AD</sub>/T<sub>CY</sub>)-1 <br />
= 2(334e-9/33.34e-9)-1 <br />
= 19<br />
<br />
char adc_open(int flags)<br />
{<br />
// Configure interrupt<br />
_ADIF = 0; //clear ADC interrupt flag<br />
_ADIE = 1; //enable adc interrupt<br />
// Configure analog i/o <br />
_TRISB0 = 1;<br />
_TRISB1 = 1; <br />
ADPCFG = 0xFFFC; //Enable AN0 (Vref+) and AN1 (Vref-)<br />
// Configure scan input channels <br />
ADCSSL = 0x0003; //0 => Skip, 1 => Scan<br />
// Configure CH0 Sample and Hold for 200kbps<br />
// +-- Use MUX A only<br />
// +-- Set CH0 S/H -ve to VRef-<br />
ADCHSbits.CH0NA = 0;<br />
// ADCCON3:<br />
// +--Auto Sample Time = 1TAD<br />
// +--A/D Conversion Clock Source = system clock<br />
// +--A/D Conversion Clock Select ADCS<5:0>= 2(TAD/TCY)-1<br />
// 200kbps(Sampling frequency)<br />
ADCON3bits.SAMC = ADC_ACQ_TIME; //1TAD for sampling time<br />
ADCON3bits.ADRC = 0; //Use system clock<br />
ADCON3bits.ADCS = ADC_ADCS; //each conversion requires 14TAD<br />
// ADCCON2:<br />
// +--Default: Use MUX A, No splitting of Buffer<br />
// +--Voltage Reference Configuration Vref+ and Vref-<br />
// +--Scan Input Selections<br />
// +--5 samples between interrupt<br />
ADCON2bits.VCFG = 3; //External Vref+, Vref-<br />
ADCON2bits.CSCNA = 1; //Scan input<br />
ADCON2bits.SMPI = 1; //take 2 samples (one sample per channel) per interrupt<br />
// ADCCON1:<br />
// +--Default: continue in idle mode, integer format<br />
// +--Enable ADC, Conversion Trigger Source Auto, Auto sampling on<br />
ADCON1bits.FORM = 0; //[0:integer]; [2 fractional]; [3 siged fractional]<br />
ADCON1bits.SSRC = 7; //auto covert, using internal clock source<br />
ADCON1bits.ASAM = 1; //auto setting of SAMP bit<br />
ADCON1bits.ADON = 1; //Turn on module<br />
return 0;<br />
}<br />
<br />
====read()====<br />
*16 registers (ADCBUF0 -ADCBUF15) are dedicated to store the ADC data between interrupts. However, the data in ADCBUFx does not necessarily correspond to the data taken for channel x. Since the lowest register will always be filled first, when some of the channels are not scanned (i.e. skipped), care must be taken. The following code checks the ADCSSL register for the current scanning channels and moves the data to the corresponding position in *adc_buf.<br />
void _ISR _ADCInterrupt(void){<br />
unsigned int channel = 0;<br />
unsigned int buffer = 0;<br />
for (; channel<ADC_MAX_CH; channel++)<br />
{<br />
if(select(channel)) //Check if channel has been selected<br />
{<br />
adc_buf[channel] = ADC16Ptr[buffer]; //Copy data to adc_buf<br />
buffer++;<br />
}<br />
}<br />
adc_data_ready = 1;<br />
DISI_PROTECT(_ADIF = 0); //Clear adc interrupt<br />
}<br />
<br />
static unsigned char select(unsigned char ch)<br />
{<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
if(ADCSSL & mask)<br />
return 1;<br />
return 0;<br />
}<br />
*User can read from the buffer at anytime to get the most updated analog values.<br />
int adc_read(unsigned int* buf, int count)<br />
{<br />
if(adc_data_ready == 1)<br />
{<br />
int num_channel = count/2; //number of channels to read<br />
unsigned char channel = adc_ch_select; //index for adc_buf<br />
int i = 0; //index for buf<br />
while(i<num_channel && channel<ADC_MAX_CH)<br />
{ <br />
//Loop only for specified number of channel or all channels <br />
buf[i++] = adc_buf[channel++]; //use data in local buffer<br />
while(select(channel)==0)<br />
{ //increment to next valid channel<br />
channel++; <br />
if(channel >= ADC_MAX_CH) break;<br />
}<br />
}<br />
return 2*i;<br />
}<br />
return -1;<br />
}<br />
<br />
====ioctl()====<br />
*This function is used to add or remove channels from the ADC scanning process.<br />
char adc_ioctl(unsigned char request, unsigned char* argp)<br />
{<br />
switch(request)<br />
{<br />
case ADC_ADD_CH:<br />
//ADD channels to current set==========================<br />
cli(); //Disable global interrupt<br />
if(select(argp[0]) == 0){ //If channel not in scan list<br />
adcAdd(argp[0]); //Add individual channel to scan list<br />
adc_data_ready = 0; //First data not ready yet, until interrupt occurs<br />
}<br />
adc_ch_select = argp[0]; //Select current channel for reading<br />
sti(); //Enable global interrupt<br />
break;<br />
case ADC_RM_CH:<br />
//REMOVE channels from current set==========================<br />
cli(); //Disable global interrupt<br />
if(select(argp[0])){ //If channel in scan list <br />
adcRm(argp[0]); //Remove individual channel<br />
adc_ch_select = 0; //Reset to AN0<br />
}<br />
sti(); //Enable global interrupt<br />
break;<br />
default:<br />
return -1; //request code not recognised <br />
}<br />
return 0;<br />
}<br />
*Channels may be added or removed by changing _TRISBX, ADPCFG, ADCSSL and ADCON2bits.SMPI.<br />
void adc_add_ch(unsigned char ch){<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
TRISB = TRISB | mask;<br />
ADCSSL = ADCSSL | mask; <br />
ADPCFG = ~ADCSSL;<br />
ADCON2bits.SMPI++; //take one more sample per interrupt<br />
}<br />
<br />
void adc_rm_ch(unsigned char ch){<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
ADPCFG = ADPCFG | mask;<br />
ADCSSL = ~ADPCFG;<br />
ADCON2bits.SMPI--; //take one less sample per interrupt<br />
}<br />
<br />
===EEPROM===<br />
<br />
----<br />
*5011 has 1024 bytes of EEPROM, readable and writable under normal voltage (5V).<br />
*To use, declare:<br />
unsigned char _EEDATA(2) eeData[1024]={ 0x00, 0x00, 0x00, 0x00, .... }<br />
unsigned int byte_pointer = 0;<br />
====lseek()====<br />
*This function moves the pointer to the desired position before a reading/writing operation is performed.<br />
int eeprom_lseek(int offset, unsigned char whence){<br />
byte_pointer = offset;<br />
return byte_pointer;<br />
}<br />
====read()====<br />
*This function read ''count'' bytes from the eeprom.<br />
int eeprom_read(unsigned char* buf, int count){<br />
int i=0;<br />
for(; i<count && byte_pointer < 1024; i++){<br />
readEEByte( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + byte_pointer, <br />
&buf[i]);<br />
byte_pointer++; //Update global pointer<br />
}<br />
return i; //read i bytes successful <br />
}<br />
*readEEByte() is implemented in assembly code as follows:<br />
.global _readEEByte<br />
_readEEByte:<br />
push TBLPAG ;w0 = base of eeData<br />
mov w0, TBLPAG ;w1 = offset for eeData in byte<br />
tblrdl.b [w1], [w2] ;w2 = pointer to user buffer<br />
pop TBLPAG<br />
return<br />
<br />
====write()====<br />
*This function write ''count'' bytes to eeprom.<br />
int eeprom_write(unsigned char* buf, int count){<br />
char isOddAddr = byte_pointer%2; //current address is odd<br />
char isOddByte = count%2; //number of bytes to write is odd<br />
//=================================================================<br />
unsigned int word_offset = byte_pointer>>1; //div by 2 and round down<br />
int max_write;<br />
max_write = (isOddAddr == 0 && isOddByte == 0) ? (count>>1) : (count>>1)+1;<br />
//=================================================================<br />
unsigned int word_data; //Store word to be written<br />
int byte_wr = 0; //number of bytes written, i.e buffer pointer<br />
int i = 0;<br />
//=================================================================<br />
for(; i<max_write && word_offset<512; i++, word_offset++){<br />
if(i==0 && isOddAddr){<br />
//First byte not used<br />
//============================================save first byte<br />
readEEByte( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + byte_pointer - 1,<br />
&word_data);<br />
//===========================================================<br />
word_data = ((unsigned int)buf[0] << 8) + (0xFF & word_data);<br />
byte_wr++; //Update buffer pointer<br />
byte_pointer++; //Update global pointer<br />
} else if(i==max_write-1 && ((isOddAddr && sOddByte==0)||(isOddAddr==0 && isOddByte))){<br />
//Last byte not used<br />
//=============================================save last byte<br />
readEEByte( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + byte_pointer + 1,<br />
&word_data);<br />
//============================================================<br />
word_data = (word_data << 8) + buf[byte_wr];<br />
byte_wr++; //Update buffer pointer<br />
byte_pointer++; //Update global pointer<br />
} else{<br />
//Both bytes valid<br />
word_data = ((unsigned int)buf[byte_wr+1] << 8) + buf[byte_wr];<br />
byte_wr+=2; //Update buffer pointer<br />
byte_pointer+=2; //Update global pointer<br />
}<br />
//==================================================================<br />
eraseEEWord( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + 2*word_offset);<br />
writeEEWord( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + 2*word_offset,<br />
&word_data);<br />
//==================================================================<br />
}<br />
return byte_wr; //No. of byte written<br />
}<br />
*eraseEEWord and writeEEWord are implemented in assembly.<br />
.global _eraseEEWord<br />
_eraseEEWord:<br />
push TBLPAG <br />
mov w0, NVMADRU ;w0 = base of eeData<br />
mov w1, NVMADR ;w1 = offset for eeData in word<br />
mov #0x4044, w0 <br />
mov w0, NVMCON ;Set to erase operation<br />
push SR ;Disable global interrupts<br />
mov #0x00E0, w0<br />
ior SR<br />
mov #0x55, w0 ;Write the KEY sequence<br />
mov w0, NVMKEY<br />
mov #0xAA, w0 <br />
mov w0, NVMKEY<br />
bset NVMCON, #15 ;Start the erase cycle, bit 15 = WR<br />
nop<br />
nop<br />
L1: btsc NVMCON, #15 ;while(NVMCONbits.WR)<br />
bra L1<br />
clr w0<br />
pop SR ;Enable global interrupts<br />
pop TBLPAG<br />
return<br />
<br />
.global _writeEEWord<br />
_writeEEWord:<br />
push TBLPAG ;w0 = base of eeData<br />
mov w0, TBLPAG ;w1 = offset for eeData in byte<br />
tblwtl [w2], [w1] ;w2 = pointer to user buffer<br />
mov #0x4004, w0 ;Set to write operation<br />
MOV w0, NVMCON<br />
push SR ;Disable global interrupts<br />
mov #0x00E0, w0<br />
ior SR<br />
mov #0x55, w0 ;Write the KEY sequence<br />
mov w0, NVMKEY<br />
mov #0xAA, w0 <br />
mov w0, NVMKEY<br />
bset NVMCON, #15 ;Start the erase cycle, bit 15 = WR<br />
nop<br />
nop<br />
L2: btsc NVMCON, #15 ;while(NVMCONbits.WR)<br />
bra L2<br />
clr w0<br />
pop SR ;Enable global interrupts<br />
pop TBLPAG<br />
return<br />
<br />
===Simple PWM (Output Compare Module)===<br />
<br />
----<br />
<br />
*The PWM module consists of 8 channels using the output compare module of dsPic.<br />
*These channels are locate at pin 46 (OC1), 49 (OC2), 50 (OC3), 51 (OC4), 52 (OC5), 53 (OC6), 54 (OC7), 55 (OC8). These pins are shared with port D.<br />
*The range of PWM freqeuencies obtainable is 2Hz to 15MHz (See Figure 6.3). Suggested range of operation is 2Hz to 120kHz. The relationship between resolution ''r'' and PWM frequency ''f''<sub>PWM</sub> is given by:<br />
f<sub>PWM</sub> = f<sub>CY</sub>/(Prescale*10<sup>rlog(2)</sup>)<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 6.3 Relationship of Resolution and PWM Frequency<br />
! Resolution (bit) !! Prescale=1 !! Prescale=8 !! Prescale=64 !! Prescale=256<br />
|- <br />
|1||15,000,000 ||1,875,000 ||234,375||58,594 <br />
|- <br />
|2||7,500,000 ||937,500 ||117,188 ||29,297 <br />
|- <br />
|3||3,750,000 ||468,750 ||58,594 ||14,648 <br />
|- <br />
|4||1,875,000 ||234,375 ||29,297 ||7,324 <br />
|- <br />
|5||937,500 ||117,188 ||14,648 ||3,662 <br />
|- <br />
|6||468,750 ||58,594 ||7,324 ||1,831 <br />
|- <br />
|7||234,375 ||29,297 ||3,662 ||916 <br />
|- <br />
|8||117,188 ||14,648 ||1,831||458 <br />
|- <br />
|9||58,594 ||7,324 ||916 ||229 <br />
|- <br />
|10||29,297 ||3,662 ||458 ||114 <br />
|- <br />
|11||14,648 ||1,831 ||229||57 <br />
|- <br />
|12||7,324 ||916 ||114 ||29 <br />
|- <br />
|13||3,662 ||458 ||57 ||14 <br />
|- <br />
|14||1,831 ||229 ||29 ||7 <br />
|- <br />
|15||916 ||114 ||14 ||4 <br />
|- <br />
|16||458 ||57 ||7 ||2 <br />
|-<br />
|}<br />
<br />
====open()====<br />
*A timer (either Timer 2 or 3) is needed to determine the pwm period. The following code uses timer 2 for all 8 channels.<br />
void pwm_open(void){<br />
OC1CON = 0; OC2CON = 0; //Disable all output compare modules<br />
OC3CON = 0; OC4CON = 0;<br />
OC5CON = 0; OC6CON = 0;<br />
OC7CON = 0; OC8CON = 0;<br />
//============================================================<br />
TMR2 = 0; // Clear register<br />
PR2 = 0xFFFF; // Set to Maximum<br />
//============================================================<br />
_T2IF = 0; // Clear interrupt flag<br />
_T2IE = 0 // Enable interrupts<br />
//============================================================<br />
T2CONbits.TCS = 0; // Use internal clock source<br />
T2CONbits.TCKPS = 0; // Prescale Select 1:1<br />
//============================================================<br />
T2CONbits.TON = 1; // Start the timer <br />
}<br />
<br />
====ioctl()====<br />
*User should select the channel and set the pwm period using the functions below before issuing the duty cycle:<br />
char pwm_ioctl(unsigned char request, unsigned long* argp){<br />
unsigned int value;<br />
unsigned char mask;<br />
switch(request){<br />
case PWM_SET_PERIOD:<br />
return setPeriodNPrescale(argp[0]);<br />
case PWM_SELECT_CH:<br />
pwm_channel = argp[0];<br />
mask = 0x01 << pwm_channel;<br />
pwm_status = pwm_status | mask;<br />
return 0;<br />
default:<br />
return -1;<br />
}<br />
}<br />
char setPeriodNPrescale(unsigned long value_ns){<br />
unsigned long ans;<br />
unsigned long long numerator = (unsigned long long)value_ns*SYSTEM_FREQ_MHZ;<br />
int index= -1;<br />
unsigned long denominator;<br />
//-------------------------------------------------<br />
do{<br />
denominator = (unsigned long)1000*pwm_prescale[++index];<br />
ans = (unsigned long)(((long double)numerator/denominator) + 0.5) - 1; //round to nearest int<br />
} while(ans > 0x0000FFFF && index < 3);<br />
//-------------------------------------------------<br />
if(ans > 0x0000FFFF)<br />
return -1;<br />
//-------------------------------------------------<br />
T2CONbits.TON = 0; // Turn off the timer<br />
T2CONbits.TCKPS = index; // Change prescale factor<br />
PR2 = (unsigned int) ans; // Set to Maximum<br />
T2CONbits.TON = 1; // Turn on the timer <br />
//-------------------------------------------------<br />
return 0;<br />
}<br />
<br />
====write()====<br />
*User can change the duty cycle using the following functions<br />
int pwm_write(unsigned long* buf){<br />
if((pwm_status & (0x01 << pwm_channel)) == 0){<br />
return -1; //Channel has not been enabled<br />
}<br />
switch(pwm_channel){<br />
case 0:<br />
OC1RS = calcDCycle(buf[0]); OC1R = OC1RS; <br />
OC1CONbits.OCM = 6; //Simple PWM, Fault pin disabled<br />
break;<br />
case 1:<br />
OC2RS = calcDCycle(buf[0]); OC2R = OC2RS; <br />
OC2CONbits.OCM = 6; //Simple PWM, Fault pin disabled<br />
break;<br />
...<br />
case 7:<br />
OC8RS = calcDCycle(buf[0]); OC8R = OC8RS; <br />
OC8CONbits.OCM = 6; //Simple PWM, Fault pin disabled<br />
break; <br />
default:<br />
return -1;<br />
}<br />
return 4;<br />
}<br />
unsigned int calcDCycle(unsigned long value_ns){<br />
unsigned long long numerator = (unsigned long long)value_ns*SYSTEM_FREQ_MHZ;<br />
unsigned int index = T2CONbits.TCKPS;<br />
unsigned long denominator = (unsigned long)1000*pwm_prescale[index];<br />
return (unsigned int)(((long double)numerator/denominator) + 0.5) - 1; //round to nearest int<br />
}<br />
<br />
====Propagration Delay====<br />
*PWM channels sharing the same timer will have their PWM signals synchronised (i.e. the HIGH state of the duty cycle are all triggered together).<br />
*To introduced delay to the PWM signals, the signal from selected channels may be made to pass through a series of inverters (e.g. 74HC14D). This adds propagation delay to the signal.<br />
*However, as propagration delay of logic gates depends on applied voltage, temperature and load capacitance, the accuracy is low and performance is poor. For accurate delay, delay lines may be used, but they are expensive.<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 6.4 Propagation Delay of [http://www.nxp.com/acrobat_download/datasheets/74HC_HCT14_3.pdf Philips 74HC14D]<sup>[1], [2]</sup><br />
! !! 3.3V !! !! !! 5.0V !! !!<br />
|- <br />
! Number of Gates !! A !! B !! C !! A !! B !! C<br />
|- <br />
| 2 <br />
| 21ns (10.5)|| 23ns (11.5)|| 22ns (11.0)<br />
| 15ns (7.5)|| 14ns (7.0)|| 14ns (7.0)<br />
|-<br />
| 4 <br />
| 45ns (11.3)|| 46ns (11.5)|| 46ns (11.5) <br />
| 30ns (7.5)|| 30ns (7.5)|| 30ns (7.5)<br />
|-<br />
| 6 <br />
| 69ns (11.5)|| 70ns (11.7)|| 72ns (12.0) <br />
| 45ns (7.5)|| 46ns (7.7)|| 47ns (7.8)<br />
|- <br />
|}<br />
[1] Data in specification for 4.5V: Typical 15ns, Maximum 25ns<br><br />
[2] Data in specification for 6.0V: Typical 12ns, Maximum 21ns<br />
<br />
===DSP Library===<br />
<br />
----<br />
*Library functions in <dsp.h> include the following categories: <br />
#Vector<br />
#Window<br />
#Matrix<br />
#Filtering<br />
#Transform<br />
#Control<br />
<br />
====Data Types====<br />
*Signed Fractional Value (1.15 data format)<br />
**Inputs and outputs of the dsp functions adopt 1.15 data format, which consumes 16 bits to represent values between -1 to 1-2<sup>-15</sup> inclusive.<br />
**Bit<15> is a signed bit, positive = 0, negative = 1.<br />
**Bit<14:0> are the exponent bits ''e''.<br />
**Positive value = 1 - 2<sup>-15</sup>*(32768 - ''e'')<br />
**Negative value = 0 - 2<sup>-15</sup>*(32768 - ''e'')<br />
*40-bit Accumulator operations (9.31 data format)<br />
**The dsp functions use the 40 bits accumalators during arithmatic calculations.<br />
**Bit<39:31> are signed bits, positive = 0x000, negative = 0x1FF.<br />
**Bit<30:0> are exponent bits.<br />
*IEEE Floating Point Values<br />
**Fractional values can be converted to Floating point values using: '''fo = Fract2Float(fr);''' for fr = [-1, 1-2<sup>-15</sup>]<br />
**Floating point values can be converted to Fractional values using: '''fr = Float2Fract(fo);''' or '''fr = Q15(fo);''' for fo = [-1, 1-2<sup>-15</sup>]<br />
**Float2Fract() is same as Q15(), except having saturation control. When +ve >= 1, answer = 2<sup>15</sup>-1 = 32767 (0x7FFF). When -ve < -1, answer = -2<sup>15</sup> = -32767 (0x8000)<br />
<br />
===Build-in Library===<br />
<br />
----<br />
*Some assembler operators can only be accessed by inline assembly code, for example, <br />
#Manuipulation of accumulators A and B (add, sub, mul, divide, shift, clear, square)<br />
#Bit toggling<br />
#Access to psv (program space visiblity) page and offset<br />
#Access to table instruction page and offset<br />
*Built-in functions are written as C-like function calls to utilize these assembler operators.<br />
<br />
<br />
==Bootloader Development==<br />
<br />
===Concepts===<br />
*Programming with ICSP is useful when the target board is produced in batch. The producer can download a program even when the chip is on the target board.<br />
*However, ICSP requires an external programmer.<br />
*To allow the user to change the program after production but without the need of an external programmer, bootloader becomes useful.<br />
*Bootloader is a small program installed via ICSP. Everytime the device is reset, the bootloader is run first. The bootloader first detects the default serial channel whether the user wishes to download a new program to the device. If so, the bootloader will pause there, and wait for the user to download the hex file from the PC. The hex file is written to the device via RTSP instructions in the bootloader. If a new download is not necessary, the bootloader redirects to the previously installed user's program.<br />
*The disadvantage of bootloaders is that they consume some of the memory of the device.<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 7.1 Free bootloaders for dsPIC<br />
! Developer<br />
! Source<br />
! Platform<br />
! User Guide<br />
! Remarks<br />
|- valign="top"<br />
| [http://www.ingenia-cat.com/index.php?lang=en ingenia]<br />
| [http://www.ingenia-cat.com/download/iBL.s Assembly]<br />
| [http://www.ingenia-cat.com/download/ingeniadsPICbootloader1.1.zip Windows]<br />
| [http://www.ingenia-cat.com/reference/pdf/iBL.UG.V1.2.pdf pdf]<br />
| <br />
*Works for all dsPIC supporting RTSP<br />
*Auto baudrate detection<br />
*Use about 1.15% of the flash memory space (0xAFFF-0xAE00)/(0xAFFF-0x0100)<br />
*Development of Linux platform is underway<br />
*Modification of code for dsPIC30F5011 is successful<br />
|-valign="top"<br />
| [http://www.etc.ugal.ro/cchiculita/software/picbootloader.htm Tiny]<br />
| [http://www.etc.ugal.ro/cchiculita/software/tinybld191.zip Assembly]<br />
| Windows<br />
| [http://www.etc.ugal.ro/cchiculita/software/tinybldusage.htm Web]<br />
| <br />
*By default, only supports 601X, 601X, 401X, 2010<br />
*Smaller code size than ingenia, but not as easy to modify<br />
|-valign="top"<br />
| [http://www.via.si/software/dsPIC_bootloader/ Elektronika]<br />
| [http://www.via.si/software/dsPIC_bootloader/data/ Hex]<br />
| Windows<br />
| [http://www.via.si/software/dsPIC_bootloader/data/README.txt txt]<br />
| <br />
*Only works for dsPIC30F6014 serial port UART2 at baudrate 57600<br />
|-<br />
|}<br />
<br />
===dsPicBootloader===<br />
<br />
*The bootloader developed by ingenia is open source and it has been modified (see below) to suit our development using dsPic30f5011.<br />
*The bootloader (hereafter called dsPicBootloader) employs the following settings:<br />
# Use U2ART channel<br />
# Use FRC, PLL16<br />
# For 5011, the bootloader is located between 0x00AE00 to 0x00AFFE (512bytes). Refer to C:\Program Files\Ingenia\ingeniadsPICbootloader\ibl_dspiclist.xml after installing the GUI interface.<br />
*Changes made to [http://www.ingenia-cat.com/download/iBL.s assembly code] includes:<br />
1. including p30f5011.gld and p30f5011.inc<br />
.include "p30f5011.inc"<br />
2. changing the config code of UART #0x8420 -> #0x8020<br />
; Uart init<br />
mov '''#0x8020''', W0 ; W0 = 0x8020 -> 1000 0000 0010 0000b<br />
mov W0, U2MODE ; Enable UART, AutoBaud and 8N1<br />
clr U2STA<br />
3. changing the start address 0xAE00 - 0x0100 = 0AD00<br />
.equ CRC, W4<br />
.equ ACK, 0x55<br />
.equ NACK, 0xFF<br />
.equ USER_ADDRESS, 0x0100<br />
.equ START_ADDRESS, '''0xAD00''' ; Relative to 0x0100<br />
4. using Internal FRC and PLL16<br />
config __FOSC, CSW_FSCM_OFF & '''FRC_PLL16''' ;Turn off clock switching and<br />
;fail-safe clock monitoring and<br />
;use the Internal Clock as the<br />
;system clock<br />
5. disabling MCLR (optional)<br />
config __FBORPOR, PBOR_ON & BORV_27 & PWRT_16 & '''MCLR_DIS'''<br />
;Set Brown-out Reset voltage and<br />
;and set Power-up Timer to 16msecs<br />
6. changing all the related registers of U1ART to U2ART, all U1XXX => U2XXX<br />
'''U2MODE, U2STA, U2BRG, U2RXREG, U2TXREG'''<br />
7. changing all the related registers of IC1 to IC2, all IC1XXX => IC2XXX<br />
'''IC2CON, #IC2IF, #IC2IE'''<br />
<br />
===dsPicProgrammer (Java-based Multi-Platformed)===<br />
*Ingenia developed a programmer (PC-side) that works only in Windows environment. The project for Linux environment is currently suspended.<br />
*A simple programmer (hereafter called dsPicProgrammer) written in Java based on the library developed by [http://www.rxtx.org/ RXTX] has been developed here. The programmer supports both Linux and Windows environments, and may be used as a substitution for the official programmer developed by ingenia.<br />
*The programmer has the following specification and limitations:<br />
#Can be used on both Linux and Windows platforms.<br />
#Adjustable baudrate (9600bps to 57600bps).<br />
#Support programming of dsPIC30F5011 and dsPIC33FJ128GP306 devices (Developers may add your devices).<br />
#Protection against overwriting bootloader codes on devices.<br />
#Detection if application program does not have its reset() at user's code start address.<br />
#Reprogramming can be done without powering down the target board, provided the user's program is compliant to that stated below.<br />
#Target board will run the user's program after programming is done.<br />
#Can be used with USB-Serial Cables. Below is a list of tested cable:<br />
::[http://www.prolific.com.tw/eng/Products.asp?ID=59 Prolific PL-2303 USB to Serial Bridge Controller]: [http://www.prolific.com.tw/eng/downloads.asp?ID=31 Driver download]<br />
<br />
===Special Consideration===<br />
*The bootloader assumes that the user program starts at address 0x100. This is usually the case, but there are always exceptions.<br />
*To ensure that the user program always starts at address 0x100, you can create a customized linker script and customized reset() function as follows:<br />
:*Copy and modify the file named "crt0.s" from the directory "C:\Program Files\Microchip\MPLAB C30\src\pic30" to the project directory and include it.<br />
.section .reset, code //previously .section .libc, code <br />
:*Copy and modify the linkerscript for the device (e.g. p30f5011.gld) to the project directory and include it.<br />
.text __CODE_BASE :<br />
{<br />
*(.reset); //<-insert this line here<br />
*(.handle);<br />
*(.libc) *(.libm) *(.libdsp); /* keep together in this order */<br />
*(.lib*);<br />
*(.text);<br />
} >program<br />
<br />
===Communication Protocol===<br />
<br />
+-------------------+ +-------------------+----------------+<br />
| dsPicProgrammer | | dsPicBootloader | User's Program |<br />
+-------------------+ +-------------------+----------------+<br />
| PC | | Target dsPic |<br />
+-------------------+ +------------------------------------+<br />
| COM PORT |=============| UART |<br />
+-------------------+ +------------------------------------+<br />
<br />
* '''Stage 1: User's Configuation'''<br />
**Select a COM port channel<br />
**Select a baudrate<br />
**Select the user hex file<br />
java -jar dsPicProgrammer.jar COM1 19200 foo.hex<br />
* '''Stage 2: Resetting Target Device'''<br />
**dsPicProgrammer sends a Break character (pull UART-TX to low logic, which is normally high).<br />
**User's program on dsPic detects the break character and reset the chip<br />
::NOTE: The user's program is expected to have the following code in order to enable this function. Otherwise, the target board must be restarted manually.<br />
void _ISR _U2RXInterrupt(void)<br />
{<br />
//No Framming error<br />
if( U2STAbits.FERR == 0)<br />
{<br />
//Normal procedure<br />
}<br />
//Framming error<br />
else<br />
{<br />
if ( U2STAbits.URXDA ){<br />
unsigned char data;<br />
data = (unsigned char) U2RXREG;<br />
if(data == 0x00){<br />
// A break char has been received: <br />
// U2RX has been pulled to zero for more than 13 bits<br />
// This is used to reboot the pic<br />
mdelay(800); //wait for break character to clear<br />
asm("reset"); //software reset<br />
}<br />
} <br />
}<br />
_U2RXIF = 0; //Clear the flag<br />
}<br />
* '''Stage 3: Entering Ingenia's Protocol'''<br />
** Transmission is conducted in 8N1, i.e. 8-bit, no parity, 1 stop-bit<br />
** Communication Protocol is reviewed in [http://www.ingenia-cat.com/reference/pdf/iBL.UG.V1.2.pdf ingenia bootloader user's guide] section 2.1.3. The following summarises the key steps on the PC side (Refer also to section 2.2.2).<br />
::#Autobaud rate detection: dsPicProgrammer continuously sends a character "U" [0x55] via COM port and waits for an acknowledgment character "U", [ACK] = [0x55]<br />
::#Version Control: dsPicProgrammer sends the command character [0x03]. On success, dsPicProgrammer receives 3 characters i) Major Version ii) Minor Version iii) Acknowledgment [0x55]<br />
::#Device ID Monitoring: dsPicProgrammer sends the read command character [0x01] + 24-bit address [High][Medium][Low] (0xFF0000). Then, it receives 4-byte data [High][Medium][Low][ACK]<br />
::#Load the user hex file and check integrity<br />
::#Start Programming: dsPicProgrammer issues the write command character [0x02] + 24-bit address [High][Medium][Low]+ Number of bytes [N] + [data 0] + [data 1] + ... + [data N-1] + [CRC]=(INTEL HEX8 Checksum - Sum modulo 256) and receives [ACK] or [NACK] = [0xFF]<br />
::NOTE: Writing is in row mode access (i.e. erase and write a whole row, each row has 32 instructions, or 96 bytes because each instruction has 24 bits)<br />
* '''Stage 4: Goto User's Program'''<br />
**dsPicProgrammer sends the goto user code command [0x0F]<br />
<br />
<br />
==USB-RS232 Bridge==<br />
<br />
*As USB ports are becoming more and more common, COM ports and Parallel ports may be redundant in the next few years. This section explore the possibilities of programming the target board through a USB port.<br />
*There are two options:<br />
#Use an external USB/RS232 adaptor, the driver will emulate a virtual COM port, such as [http://www.prolific.com.tw/eng/downloads.asp?ID=31 Prolific] and [http://www.ftdichip.com/Drivers/VCP.htm FDTI]. Ingenia has tested its bootloader with some USB-232 manufacturers (silabs, FTDI, etc..). However, the programming failed with our Prolific adapter. Application program may use [http://java.sun.com/products/javacomm/ JavaComm API] (javax.comm) and/or [http://www.rxtx.org/ RXTX] to drive the COM port.<br />
#Modified the bootloader program on PC to support USB communication. e.g. using [http://jusb.sourceforge.net/ jUSB] and [http://javax-usb.org/ JSR-80] (javax.usb). External circuits such as PIC18F4550 and MAX232 are required.<br />
<br />
|--User's App.--|-------Device Manager------|-------USB-RS232 Interface------|---dsPIC---|<br />
Option 1:<br />
+-------------+ +----------+ +----------+ +---+ +------------+ +-----+ +--------+<br />
| Application |--| JavaComm |--| Virtual |==|USB|--| FDTI |--|RS232|==| Target |<br />
| Program | | RXTX | | COM Port | +---+ | Circuitary | +-----+ | Board |<br />
+-------------+ +----------+ +----------+ +------------+ +--------+<br />
Option 2:<br />
+-------------+ +--------+ +---+ +------------+ +-----+ +--------+<br />
| Application |----------| JSR-80 |==========|USB|--| PIC18F4550 |--|RS232|==| Target |<br />
| Program | | jUSB | +---+ | MAX232 | +-----+ | Board |<br />
+-------------+ +--------+ +------------+ +--------+<br />
<br />
*Currently, when RXTX is incorporated with JavaComm API, operating systems supported include Linux, Windows, Mac OS, Solaris and other operating systems. On the other hand, jUSB and JSR-80 only works for linux.<br />
<br />
===FDTI Chipset===<br />
*FT232RL communicates with PC via USB to provide 1 UART channel.<br />
*Datasheet can be downloaded [http://www.ftdichip.com/Documents/DataSheets/DS_FT232R.pdf here]. <br />
**Refer to Fig. 11 (Page 19) for Bus Powered Configuration.<br />
**Refer to Fig. 16 (Page 24) for for UART TTL-level Receive [RXD -> 1], Transmit [TXD -> 4], Transmit Enable [CBUS2/TXDEN -> 3]. Omit Receive Enable [CBUS3/PWREN#] and use [CBUS2/TXDEN -> 2] <br />
**Refer to Fig. 15 (Page 23) for LED Configuration: [CBUS0/TXLED#] and [CBUS1/RXLED#]<br />
*Virtual COM Port Drivers can be downloaded [http://www.ftdichip.com/Drivers/VCP.htm here].<br />
<br />
<br />
==Programming the Device==<br />
<br />
===Requirements===<br />
*Hardware<br />
#PC with COM port (Windows XP Installed for MPLAB)<br />
#ICD2 Programmer<br />
#Target Board<br />
#5V Power Supply<br />
<br />
*Software<br />
#[http://ww1.microchip.com/downloads/en/DeviceDoc/MP750.zip MPLAB IDE v7.50]: v7.60 is not compatible with our current [http://www.sure-electronics.com/ ICD2 Programmers]. There are consistent "Devices cannot be founded" warnings.<br />
#[http://chungyan5.no-ip.org/websvn/listing.php dsPicProgrammer] ('''dsPicProgrammer.jar''')<br />
#[http://users.frii.com/jarvi/rxtx/download.html RXTX driver]: download and upzip rxtx-2.1-7-bins-r2.zip (Final)<br />
<br />
*Files<br />
#[http://chungyan5.no-ip.org/websvn/listing.php dsPicBootloader] ('''bl_5011.hex'''). Original assembly code by ingenia can be downloaded from [http://www.ingenia-cat.com/download/iBL.s here].<br />
#Application hex file (e.g. '''app.hex''')<br />
<br />
===Loading Bootloader (Once only)===<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 9.1 Loading Bootloader<br />
! Step !! Remarks <br />
|-valign="top"<br />
| Install [http://ww1.microchip.com/downloads/en/DeviceDoc/MP750.zip MPLAB IDE] || <br />
*Do '''NOT''' connect ICD 2 (via USB) to PC<br />
*Execute '''MPLAB vX.XX Install.exe'''<br />
|-valign="top"<br />
| Install USB Driver ||<br />
*Follow the instruction in (C:\Program Files\Microchip\MPLAB IDE\ICD2\Drivers\Ddicd2.htm)<br />
|-valign="top"<br />
| Select Target Chip ||<br />
*Run MPLAB IDE on PC<br />
*Select: Configure>Select Devices...<br />
*Choose dsPIC30F5011<br />
|-valign="top"<br />
| Target <-> ICD 2 ||<br />
*Use six pin cable. Beware of the pin assignments. Only pin 1 - 5 should be used.<br />
*Place Jumper on target board (if any). The Jumper connects target V<sub>cc</sub> to ICD 2.<br />
*Do '''NOT''' power-up the target.<br />
|-valign="top"<br />
| ICD 2 <-> PC ||<br />
*Plug-in ICD 2 to PC via USB cable<br />
*Power-up the target.<br />
*Select: Programmer>Select Programmer>MPLAB ICD 2<br />
*If this is the first time the ICD 2 is connected to PC, MPLAB IDE will automatically download the required OS to ICD 2, wait until it has finished<br />
*If you have not connected and powered up the target, you might see Warnings on invalid device IDs, and/or running self tests.<br />
*See results of self test if necessary: Programmer>Settings, Status Tab. Refer to [http://ww1.microchip.com/downloads/en/DeviceDoc/51331B.pdf ICD2 User's Guide] Chapter 7.<br />
|-valign="top"<br />
| Load Bootloader ||<br />
*Select: File>Import...<br />
*Select '''bl_5011.hex'''<br />
|-valign="top"<br />
| Start Programming ||<br />
*Select: Programmer>Program<br />
|-valign="top"<br />
| Finishing ||<br />
*Power-down the Taget<br />
*Select: Programmer>Select Programmer>None<br />
*Unplug USB cable<br />
|-<br />
|}<br />
<br />
===Loading Firmware===<br />
<!--using Firefox-File-Page_Setup-Format-Scale-85% to print --><br />
====Java Environment Setup====<br />
*Download and install the latest JDK or JRE<br />
**Available from [http://java.sun.com/javase/downloads/index.jsp Sun Microsystems] (e.g. JDK 6 Update 3)<br>[[Image:1 1 java.JPG]]<br><br />
*Download and Extract RXTX Driver <br />
**Available from [http://users.frii.com/jarvi/rxtx/download.html RXTX] <br />
**File: rxtx-2.1-7-bins-r2.zip (Final)<br />
**Extract the files using software such as WinRAR<br>[[Image:1 2 rxtx.JPG]]<br><br />
*Copy RXTXcomm.jar<br />
**To C:\Program Files\Java\X\lib\ext (under the latest jre, e.g. X = jre1.6.0_03)<br>[[Image:1 3 rxtxcomm.JPG]]<br><br />
*Copy rxtxSerial.dll<br />
**To C:\Program Files\Java\X\bin (under the lastest jre, e.g. X = jre1.6.0_03)<br />
**For Linux users, copy librxtxSerial.so to /jre/lib/[machine type] (i386 for instance)<br>[[Image:1 4 rxtxserial.JPG]]<br><br />
*Download dsPicProgrammer <br />
**Available from [http://chungyan5.no-ip.org/websvn/listing.php?repname=repos+1&path=%2FdsPicProgrammer%2Ftags%2F&rev=0&sc=0 here]<br />
**Expand the latest tag under dsPicProgrammer<br />
**File: dsPicProgrammer.jar<br>[[Image:1 5 dspicprogrammer.JPG]]<br><br />
**Save the file (dsPicProgrammer.jar) and your hex file (foo.hex) to your local directory (e.g. C:\dsPicProgrammer\)<br>[[Image:1 6 dspicprogrammer2.JPG]]<br><br />
<br />
====Download Firmware====<br />
*Start a Command Prompt<br />
**Start -> Run<br>[[Image:2 1 run.JPG]]<br><br />
**Enter cmd<br>[[Image:2 2 cmd.JPG]]<br><br />
*Run dsPicProgrammer<br />
**Change to the directory where dsPicProgrammer.jar is located and run the command:<br>java -jar dsPicProgrammer.jar COM1 57600 foo.hex (Windows)<br>java -jar dsPicProgrammer.jar /dev/ttyS0 57600 foo.hex (Linux)<br>where COM1 is your COM Port ID<br>57600 is communication speed [in bps]<br>foo.hex is your firmware new file<br>[[Image:2 3 command.JPG]]<br><br />
**When the program prompt you for an input, press y:<br>[[Image:2 4 prompt.JPG]]<br><br />
**If communication can be established, you should see something like this:<br>[[Image:2 5 progress.JPG]]<br><br />
**Wait until programming is completed.<br>[[Image:2 6 complete.JPG]]<br><br />
**after all completed, power OFF your device, then power ON again, enjoy your new updated.<br />
<br />
====Troubleshooting====<br />
*Invalid COM Port<br />
**In case of selecting an invalid COM port, you should see the error message:<br>gnu.io.NoSuchPortException: Choosing COM Port Error<br>[[Image:3 1 com err.JPG]]<br><br />
*Missing firmware file<br />
**In case of selecting a firmware file that does not exist, you should see the error message:<br>java.io.FileNotFoundException: foo1.hex <The system cannot find the file specified><br>[[Image:3 2 file err.JPG]]<br><br />
*Missing RXTX driver<br />
**In case of missing the RXTX driver, you should see the error message:<br>Exception in thread “main” java.lang.NoClassDefFoundError: gnu/io/UnsupportedCommOperationException<br>[[Image:3 3 rxtx err.JPG]]<br><br />
<br />
==Remote Access==<br />
*At the moment, local devices (e.g. EEPROM, ADC, DAC, etc.) can only be accessed locally through POSIX functions such as open(), read(), write(), ioctl().<br />
*However, a client may need to access these devices on a remote server. This section reviews the background and gives some ideas on its possible implementation.<br />
<br />
===Requirements===<br />
*A remote file access protocol, to transfer "files" (i.e. device's data) such as:<br />
#[http://en.wikipedia.org/wiki/FTP File Transfer Protocol] (FTP): Required files are copied from sever to client for manipulation<br />
#[http://en.wikipedia.org/wiki/Remote_Shell Remote Shell] (RSH): Required files are copied from sever to client for manipulation<br />
#[http://en.wikipedia.org/wiki/Network_File_System_%28Sun%29 Network File System] (NFS): Required files are manipulated on sever<br />
*An API to access files using a selected protocol, such as:<br />
#[http://www.die.net/doc/linux/man/man2/lam_rfposix.2.html lam_rfposix]: A POSIX-like remote file service for Local Area Multicomputer<br />
#API employed by VxWorks: [http://en.wikipedia.org/wiki/VxWorks VxWorks] is a Unix-like real-time operating system, commonly used for embedded systems.<br />
<br />
===API Reference for VxWorks===<br />
*Reference:<br />
**[http://www.windriver.com/vxworks/ VxWorks Official Website]<br />
**[http://www-cdfonline.fnal.gov/daq/commercial/ OS Libraries API Reference]<br />
*Related Libraies<br />
**netDrv (netDrv.h): an API using FTP or RSH<br />
**nfsDrv (nfsDrv.h): an API using NFS<br />
<br />
<br />
==Conversion to dsPIC33F Devices==<br />
*This section discusses the conversion required from dsPIC30F5011 to dsPIC33FJ128GP306.<br />
*Refer to official document [http://ww1.microchip.com/downloads/en/DeviceDoc/70172A.pdf dsPIC30F to dsPIC33F Conversion Guidelines] (DS70172A).<br />
*Note that this section does not mainly intend to introduce the new functionalities of dsPIC33F devices. It only serves the purpose to summarise the major (if not minimum) changes required to port the setup of dsPIC30 to dsPIC33 devices.<br />
<br />
===Hardware===<br />
*dsPIC33 operates at voltage of 3.3V. A voltage regulator, such as [http://www.national.com/ds.cgi/LM/LM3940.pdf LM3940] can be used to convert 5V supply to 3.3V.<br />
*A 1uF capacitor has to be placed at pin 56 (previously V<sub>SS</sub>, now V<sub>DDCORE</sub>).<br />
<br />
===Software===<br />
<br />
====Configuration Bits====<br />
<br />
----<br />
*dsPIC33 can operate at 40MIPs at maximum. To configure the device using internal FRC, replace the configuration bits setting as follows:<br />
_FOSCSEL(FNOSC_FRCPLL); // FRC Oscillator with PLL<br />
_FOSC(FCKSM_CSDCMD & OSCIOFNC_ON & POSCMD_NONE); <br />
// Clock Switching and Fail Safe Clock Monitor is disabled<br />
// OSC2 Pin Function: OSC2(RC15) as Digital IO<br />
// Primary Oscillator Mode: Disabled<br />
_FWDT(FWDTEN_OFF); // Watchdog Timer Enabled/disabled by user software <br />
*Configure on-chip PLL at runtime as follows (at start of main function):<br />
_PLLDIV = 38; // M=40: PLL Feedback Divisor bits<br />
CLKDIV = 0; // N1=2: PLL VCO Output Divider Select bits<br />
// N2=2: PLL Phase Detector Input Divider bits<br />
OSCTUN = 22; // Tune FRC oscillator, if FRC is used; <br />
// 0: Center frequency (7.37 MHz nominal)<br />
// 22: +8.25% (7.98 MHz)<br />
RCONbits.SWDTEN = 0; // Disable Watch Dog Timer<br />
while(OSCCONbits.LOCK != 1); // Wait for PLL to lock<br />
<br />
====UART====<br />
<br />
----<br />
*No change is required.<br />
<br />
====I2C====<br />
<br />
----<br />
*dsPIC33 supports upto 2 I<sup>2</sup>C devices. As a result, replace all I<sup>2</sup>C related registers with xxI2Cyy to xxI2C'''1'''yy. For examples:<br />
_SI2C1IF = 0; //Clear Slave interrupt<br />
_MI2C1IF = 0; //Clear Master interrupt<br />
_SI2C1IE = 0; //Disable Slave interrupt<br />
_MI2C1IE = 0; //Disable Master interrupt<br />
I2C1BRG = I2C_BRG; // Configure Baud rate<br />
I2C1CONbits.I2CEN = 1;<br />
...<br />
etc.<br />
<br />
====ADC====<br />
<br />
----<br />
*The ADC in dsPic33 is significantly different from that in dsPic30. Specifically, ADC in dsPic33 uses DMA to buffer the adc data. Replace the open, interrupt routine, add and remove codes as follows:<br />
<br />
unsigned int adc_bufA[ADC_MAX_CH] __attribute__((space(dma),aligned(256)));<br />
unsigned int adc_bufB[ADC_MAX_CH] __attribute__((space(dma),aligned(256)));<br />
unsigned int* ADC16Ptr; //Pointer to ADC register buffer, <br />
unsigned char adc_ch_select = 0; //Pointer to channel to be read from<br />
unsigned char adc_data_ready = 0; //Indicate if RAM data is ready for output<br />
unsigned int which_dma = 0; //indicate which adc_buf to be used<br />
<br />
void adc_open(void)<br />
{<br />
// Configure interrupt<br />
_AD1IF = 0; //clear ADC interrupt flag<br />
_AD1IE = 0; //disable adc interrupt<br />
AD1CHSbits.CH0NA = 0;<br />
// Configure analog i/o <br />
_TRISB0 = 1;<br />
_TRISB1 = 1; <br />
AD1PCFG = 0xFFFC; //Enable AN0 (Vref+) and AN1 (Vref-)<br />
AD1PCFGH = 0xFFFF; //AN16-AN31: Disabled<br />
// Configure scan input channels <br />
AD1CSSL = 0x0003; //0 => Skip, 1 => Scan<br />
AD1CSSH = 0x0000; //Skipping AN16-AN31<br />
// ADCCON4:<br />
AD1CON4bits.DMABL = 0; // Each buffer contains 1 word<br />
// ADCCON3:<br />
AD1CON3bits.SAMC = 1; //1TAD for sampling time<br />
AD1CON3bits.ADRC = 0; //Use system clock<br />
AD1CON3bits.ADCS = ADC_ADCS; //each conversion requires 14TAD<br />
// ADCCON2:<br />
AD1CON2bits.VCFG = 3; //External Vref+, Vref-<br />
AD1CON2bits.CSCNA = 1; //Scan input<br />
AD1CON2bits.SMPI = 1; //2 channels are scanned<br />
// ADCCON1:<br />
AD1CON1bits.FORM = 0; //[0:integer]; [2 fractional]; [3 siged fractional]<br />
AD1CON1bits.SSRC = 7; //auto covert, using internal clock source<br />
AD1CON1bits.ASAM = 1; //auto setting of SAMP bit<br />
AD1CON1bits.AD12B = 1; //12-bit, 1-channel ADC operation<br />
AD1CON1bits.ADDMABM = 0; // DMA buffers are built in scatter/gather mode<br />
AD1CON1bits.ADON = 1; // Turn on the A/D converter<br />
// DMA0 Configuration:<br />
DMA0CONbits.AMODE = 2; // Configure DMA for Peripheral indirect mode<br />
DMA0CONbits.MODE = 2; // Configure DMA for Continuous Ping-Pong mode<br />
DMA0PAD=(int)&ADC1BUF0; <br />
DMA0CNT = 1; // generate dma interrupt every 2 samples <br />
// same as SMPI because only 1 dma buffer per channel <br />
DMA0REQ = 13; // Select ADC1 as DMA Request source<br />
DMA0STA = __builtin_dmaoffset(adc_bufA); <br />
DMA0STB = __builtin_dmaoffset(adc_bufB);<br />
_DMA0IF = 0; // Clear the DMA interrupt flag bit<br />
_DMA0IE = 1; // Set the DMA interrupt enable bit<br />
DMA0CONbits.CHEN=1; // Enable DMA<br />
}<br />
<br />
void _ISR _DMA0Interrupt(void)<br />
{<br />
ADC16Ptr = (which_dma == 0)? adc_bufA : adc_bufB; //Update pointer<br />
adc_data_ready = 1;<br />
which_dma ^= 1; //Next buffer to be used<br />
_DMA0IF = 0; //Clear the DMA0 Interrupt Flag<br />
}<br />
<br />
static void adcAdd(unsigned char ch){<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
TRISB = TRISB | mask;<br />
AD1CSSL = AD1CSSL | mask; <br />
AD1PCFG = ~AD1CSSL;<br />
AD1CON2bits.SMPI++; //take one more sample per interrupt<br />
DMA0CNT++; <br />
}<br />
<br />
static void adcRm(unsigned char ch){<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
AD1PCFG = AD1PCFG | mask;<br />
AD1CSSL = ~AD1PCFG;<br />
AD1CON2bits.SMPI--; //take one less sample per interrupt<br />
DMA0CNT--; <br />
}<br />
<br />
====EEPROM====<br />
<br />
----<br />
*There is no EEPROM in dsPIC33 devices. Please consider to use an external EEPROM using I<sup>2</sup>C communication.<br />
<br />
====Simple PWM====<br />
<br />
----<br />
*No change is required.<br />
<br />
===Memory Map for dsPIC33FJ128GP306===<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 11.1 Memory Location<br />
! Type !! Start Address !! End Address !! Size<br />
|-valign="top"<br />
| Flash || 0x000000 ||0x0157FF || 86K<sup>[1]</sup><br />
|-valign="top"<br />
| +--Flash: Reset Vector || 0x000000 ||0x000003 || 4<br />
|-valign="top"<br />
| +--Flash: Interrupt Vector Table || 0x000004 ||0x0000FF || 252<br />
|-valign="top"<br />
| +--Flash: Alternate Vector Table || 0x000104 ||0x0001FF || 252<br />
|-valign="top"<br />
| +--Flash: User Program || 0x000200 ||0x0157FF || 85.5K<br />
|-valign="top"<br />
| Programming Executive || 0x800000 || 0x800FFF || 4K<sup>[1]</sup><br />
|-valign="top"<br />
| Config Registers || 0xF80000 || 0xF80017 || 24<br />
|-valign="top"<br />
| Device ID (0xE5) || 0xFF0000 || 0xFF0003 || 4<br />
|-<br />
|}<br />
[1] Each address is 16-bit wide. Every two addresses correspond to a 24-bit instruction. Each even address contains 2 valid bytes; each odd address contains 1 valid byte plus 1 phathom byte.<br><br />
<br />
===Custom Linker Script to Maximize Space for Constant Data===<br />
*Constant data declared using keyword '''const''' will be stored in the .const section in the flash memory.<br />
*Normally, during compilation, the linker will assign these data after the program code (.text section).<br />
*Since .const is accessed by auto-psv function, to maximize the space for constant data (32kb), the .const section needs to be aligned at 0x80000 boundary.<br />
*This requires the following change in linker script:<br />
<br />
__CONST_BASE = 0x8000;<br />
<br />
.text __CODE_BASE :<br />
{<br />
*(.reset);<br />
*(.handle);<br />
*(.libc) *(.libm) *(.libdsp); /* keep together in this order */<br />
*(.lib*);<br />
/* *(.text); deleted to maximize space for const data */<br />
} >program<br />
<br />
.const __CONST_BASE :<br />
{<br />
*(.const);<br />
} >program<br />
<br />
*If your program is large, after this change in linker script, function calls may involve large jump in the memory map (>32kB). As a result, you may need to enable the large code and large memory model during compilation. In such case, use the following options in your build path:<br />
-mlarge-code -mlarge-data<br />
*Meanwhile, functions that are defined in the standard C libraries, but are replaced with your own implementations (e.g. I/O stubs: open(), read(), write(), lseek(), ioctl() etc.) may have the following linker error:<br />
/usr/pic30-elf/lib//libc-elf.a(fflush.eo)(.libc+0x3c): In function '.LM11':<br />
: Link Error: relocation truncated to fit: PC RELATIVE BRANCH _write<br />
/usr/pic30-elf/lib//libc-elf.a(fclose.eo)(.libc+0x42): In function '.LM18':<br />
: Link Error: relocation truncated to fit: PC RELATIVE BRANCH _close <br />
*To resolve the problem, you need to place the functions in the .libc section rather than in the .text section, like this:<br />
#define LIBC_CODE_LOC __attribute__ ( (section(".libc")))<br />
<br />
int LIBC_CODE_LOC open(const char *pathname, int flags){ ... }<br />
int LIBC_CODE_LOC close(int fd){ ... }<br />
int LIBC_CODE_LOC write(int fd, void* buf, int count) { ... }<br />
int LIBC_CODE_LOC read(int fd, void* buf, int count) { ... }<br />
int LIBC_CODE_LOC ioctl(int fd, int request, void* argp) { ... }<br />
int LIBC_CODE_LOC lseek(int fd, int offset, int whence) { ... }<br />
<br />
===dsPicBootloader and dsPicProgrammer===<br />
*RTSP for dsPIC33F is different from dsPIC30F.<br />
**Row size changes from 32 instructions (96bytes) to 64 instructions (192 bytes)<br />
**Erase operation changes from 1 row to 8 rows<br />
**No EEPROM<br />
*With regards to the above changes, dsPicBootloader and dsPicProgrammer has been modified. In particular, dsPicProgrammer can be used to program both dsPic30F and dsPic33F devices. You can easily add your devices to the source code.<br />
<br />
<br />
==Downloads==<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 12.1 Related software download links for dsPicBootloader and dsPicProgrammer<br />
! Program<br />
! Site 1<br />
! Site 2<br />
! Remarks<br />
|- valign="top"<br />
| JDK<br />
| [http://java.sun.com/javase/downloads/index.jsp website]<br />
| <br />
| Download latest JDK<br />
|- valign="top"<br />
| RXTX<br />
| [http://users.frii.com/jarvi/rxtx/download.html website]<br />
| <br />
| Download rxtx-2.1-7-bins-r2.zip or later<br />
|- valign="top"<br />
| dsPicBootloader v1.3<br />
| [http://chungyan5.no-ip.org/websvn/listing.php click]<br />
| [http://www.opencircuits.com/images/a/a7/DsPicBootloader_1_3_1.zip click]<br />
| Under "dsPicBootloader/", download bl_5011.s or bl_j128gp306.s<br />
|-valign="top"<br />
| dsPicProgrammer v1.3.5<br />
| [http://chungyan5.no-ip.org/websvn/listing.php click]<br />
| [http://www.opencircuits.com/images/9/9e/DsPicProgrammer_1_3_5.zip click]<br />
| Under "dsPicProgrammer/", dowload dsPicProgrammer.jar<br><br>Alternatively, if you want to compile yourself or modify the source code, download <br>all source files under "dsPicProgrammer/" '''plus''' RdFileIntelHex.java under <br>"IntelHexPaser/tags/0.02.00/".<br>You should also install RXTX on your local machine as recommended in the readme file.<br />
|- valign="top"<br />
| Ingenia's bootloader<br />
| [http://www.ingenia-cat.com/en/downloads.php website]<br />
| <br />
| Download original ingenia's bootloader<br />
|-<br />
|}</div>Yanhttp://www.opencircuits.com/index.php?title=DsPIC30F_5011_Development_Board&diff=13153DsPIC30F 5011 Development Board2008-01-16T09:05:16Z<p>Yan: /* Download Firmware */ adding power OFF, then ON again to make sure all start to run again.</p>
<hr />
<div>==Introduction==<br />
<br />
===Features of dsPIC30F5011===<br />
*2.5 to 5V <br />
*Up to 30MIPs<br />
*High current/sink source I/O pins: 25mA<br />
*DSP Instruction Set<br />
*Dual programming techniques: ICSP and RTSP<br />
*UART: up to 2 modules<br />
*I<sup>2</sup>C: up to 1Mbps<br />
*10-bit A/D, 1.1 Msps <br />
*12-bit A/D, 200 ksps<br />
*44K flash (66Kb), 4Kb RAM, 1Kb EEPROM<br />
*No DAC<br />
*Pin-to-pin compatible with other dsPICs<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 1.1 Comparison with Compatible dsPICs<br />
! dsPic !! Price<br>US$ !! MIPs<br />
! Flash<br>(kB)!! RAM<br>(kB) !! EEPROM<br>(kB)<br />
! I/O !! ADC<br>12-bit !! IC !! OC !! Motor<br>Ctrl !! Timers<br />
! QEI !! UART !! SPI !! I2C !! CAN !! Codec<br />
|- <br />
| 30F5011 || 5.91 || 30<br />
| 66 || 4 || 1<br />
| 52 || 16 || 8 || 8 || 0 || 5x16bit<br>2x32bit<br />
| 0 || 2 || 2 || 1 || 2 || 1<br />
|-<br />
| 30F6011A || 7.73 || 30<br />
| 132 || 6 || 2<br />
| 52 || 16 || 8 || 8 || 0 || 5x16bit<br>2x32bit<br />
| 0 || 2 || 2 || 1 || 2 || 0<br />
|-<br />
| 30F6012A || 7.85 || 30<br />
| 144 || 8 || 4<br />
| 52 || 16 || 8 || 8 || 0 || 5x16bit<br>2x32bit<br />
| 0 || 2 || 2 || 1 || 2 || 1<br />
|- <br />
| 33FJ128GP206 || 4.62 || 40<br />
| 128 || 8 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 1 || 0 || 1<br />
|-<br />
| 33FJ128GP306 || 4.81 || 40<br />
| 128 || 16 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 2 || 0 || 1<br />
|-<br />
| 33FJ128GP706 || 5.49 || 40<br />
| 128 || 16 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 2 || 2 || 1<br />
|-<br />
| 33FJ128MC506 || 4.97 || 40<br />
| 128 || 8 || 0<br />
| 53 || 16 || 8 || 8 || 8 || 9x16bit<br>4x32bit<br />
| 1 || 2 || 2 || 2 || 1 || 0<br />
|-<br />
| 33FJ128MC706 || 5.38 || 40<br />
| 128 || 16 || 0<br />
| 53 || 16 || 8 || 8 || 8 || 9x16bit<br>4x32bit<br />
| 1 || 2 || 2 || 2 || 1 || 0<br />
|-<br />
| 33FJ256GP506 || 6.11 || 40<br />
| 256 || 16 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 2 || 1 || 1<br />
|-<br />
|}<br />
<br />
===Web Page===<br />
*[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2529&param=en024856 Microchip Official Website]<br />
<br />
===Forum===<br />
*[http://direct.forum.microchip.com/default.aspx Microchip]: Official forum by Microchip<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=49 MPLAB ICD 2]: Subforum on ICD 2 programmer<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=57 MPLAB IDE]: Subforum on IDE<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=101 MPLAB C30 Compiler, ASM30, Link30 forum]: Subforum on C compiler. Refer to [http://ww1.microchip.com/downloads/en/DeviceDoc/C30_Users_Guide_51284e.pdf MPLAB C30 C Compiler User's Guide] Chapter 3<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=153 dsPIC30F Topics]: Subformum on dsPIC30F<br />
*[http://www.gnupic.org/ GNUPIC]: Discussion on PIC in Linux Systems<br />
**[http://www.linuxhacker.org/cgi-bin/ezmlm-cgi?1:dds:5443#b Debian]<br />
*[http://www.htsoft.com/forum/all/ubbthreads.php/Cat/0/C/6 HI-TECH Software Forum]: Discussion on dsPICC, a C compiler developed by HI-TECH<br />
*[http://piclist.com/techref/piclist/index.htm PICList]: Discussion on older PIC systems (not dsPIC)<br />
*[http://groups.google.com/group/pickit-devel PicKit]: Discussion on PICkit/PICkit 2 programmers<br />
*[http://sourceforge.net/forum/forum.php?forum_id=382005 FreeRTOS Real Time Kernel]: Open Discussion and Support on FreeRTOS <br />
<br />
===References===<br />
*dsPIC30F<br />
**[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2574 dsPIC30F Family Reference Manual Sections]: Contains detailed descriptions on dsPIC30F register definitions and example codes<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80169E.pdf dsPIC30F Family Reference Manual Errata (Use with revision 70046B only)]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70116F.pdf dsPIC30F5011, dsPIC30F5013 Data Sheet]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80210e.pdf dsPIC30F5011/5013 Rev. A1/A2 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80223D.pdf dsPIC30F5011/5013 Rev. A3 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70102G.pdf Flash Programming Specification]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70157B.pdf dsPIC30F Programmer's Reference Manual]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80170a.pdf dsPIC30F Programmer's Reference Manual Errata (use with revision DS70030E only)]<br />
<br />
*dsPIC33F<br />
**[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2573 dsPIC33F Family Reference Manual Sections]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70165E.pdf dsPIC33F Family Data Sheet]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80279B.pdf dsPIC33F Rev. A2 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80306A.pdf dsPIC33FJXXXGPX06/X08/X10 Rev. A2 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70152C.pdf Flash Programming Specification]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70172A.pdf dsPIC30F to dsPIC33F Conversion Guidelines]<br />
*ICD2 Programmer<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/51331B.pdf ICD2 User's Guide] <br />
*MPLAB<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/51519B.pdf MPLAB IDE User's Guide]<br />
*C30 Compiler<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/C30_Users_Guide_51284e.pdf MPLAB C30 C Compiler User's Guide]: Contains commands for using pic30-elf-gcc <br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/16bit_Language_Tool_Libraries_51456c.pdf 16-bit Language Tools Libraries]: Contains summaries and examples of using DSP libraries, standard C libraries and device libraries<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/Asm30_Link_Util_51317e.pdf MPLAB ASM30, MPLAB LINK30 and Utilities User's Guide]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/51322d.pdf dsPIC30F Language Tools Quick Reference Card]<br />
<br />
===Code Examples===<br />
*[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1408 Microchip Example Codes for dsPic]<br />
<br />
<br />
==Programming Methods==<br />
*There are 2 programming methods: In-Circuit Serial Programming (ICSP) and Run-Time Self-Programming (RTSP)<br />
*ICSP allows the devices to be programmed after being placed in a circuit board.<br />
*RTSP allows the devices to be programmed when an embedded program is already in operation.<br />
<br />
===ICSP: External Programmer (ICD2)===<br />
*Two types of ICSP are available: '''ICSP''' and '''Enhanced ICSP'''. Both of them require setting MCLR# to V<sub>IHH</sub> (9V – 13.25V).<br />
*Standard ICSP<br />
**Use external programmer (e.g. MPLAB<sup>®</sup> ICD 2, MPLAB<sup>®</sup> PM3 or PRO MATE<sup>®</sup> II) only.<br />
**Required low-level programming to erase, program and verify the chip.<br />
**Slower, because codes are serially executed.<br />
**Program memory can be erased using ''Normal-Voltage'' (4.5 – 5.5V) or ''Low-Voltage'' (2.5V – 4.5V).<br />
<br />
*Enhanced ICSP<br />
**Use external programmer and '''Programming Executive''' (PE).<br />
**PE is stored in the on-chip memory.<br />
**PE allows faster programming.<br />
**PE can be downloaded to the chip by external programmer using the standard ICSP method.<br />
**PE contains a small command set to erase, program and verify the chip, avoiding the need of low-level programming.<br />
<br />
====Hardware Interface====<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.1 Pin Used by ICSP<br />
! Pin Label !! Function !! Pin Number<br />
|- <br />
| MCLR# || Programming Enable|| 7<br />
|-<br />
| V<sub>DD</sub> || Power Supply || 10, 26, 38, 57<br />
|-<br />
| V<sub>SS</sub> || Ground || 9, 25, 41, 56<br />
|- <br />
| PGC || Serial Clock || 17<br />
|-<br />
| PGD || Serial Data || 18<br />
|-<br />
|}<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.2 Available Programmers in the Market<br />
! Product Name<br />
! Interface with PC<br />
! Interface with Device<br />
! Price (US)<br />
! Postage (US)<br />
! Total (US)<br />
|- <br />
| [http://direct.www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en010046&part=DV164005 MPLAB<sup>®</sup> ICD 2]<br />
| USB or RS232<br />
| [http://www.microchip.com/Microchip.WWW.SecureSoftwareList/secsoftwaredownload.aspx?device=en010046&lang=en&ReturnURL=http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en010046&part=DV164005# 6-PIN RJ-12 connector]<br />
| $159.99<br />
| -<br />
| -<br />
|-<br />
| [http://www.etekronics.com/product_info.php?cPath=24&products_id=48 Full Speed USB Microchip ICD2<br> Debugger and Programmer]<br />
| USB<br />
| 6-PIN ICSP connector<br>6-PIN RJ-12 connector<br />
| $72.00<br />
| $12.00<br />
| $84.00<br />
|-<br />
| [http://www.etekronics.com/product_info.php?cPath=24&products_id=47 Mini Microchip Compatible ICD2<br> Debugger and Programmer]<br />
| RS232<br />
| 6-PIN ICSP connector<br>6-PIN RJ-12 connector<br />
| $45.00<br />
| $10.00<br />
| $55.00<br />
|-<br />
| [http://www.inexglobal.com/microcontroller.php ICDX30]<br />
| RS232<br />
| 6-pin RJ-11<br />
| $51.00<br />
| $47.46<br />
| $98.46<br />
|-<br />
| *[http://www.sure-electronics.net Clone Microchip ICD2] (Now Using)<br />
| USB<br />
| 6-pin flat cables<br />
| $30.00<br />
| $12.00<br />
| $42.00<br />
|-<br />
|}<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.3 DIY ICD 2 Programmer Circuit<br />
! Source !! Schematic !! PIC16F877A Bootloader<br />
|- <br />
| [http://membres.lycos.fr/silicium31/Electronique/PIC/FreeIcdEnglish.htm Patrick Touzet]<br />
| [http://membres.lycos.fr/silicium31/Electronique/PIC/ICD2%20V1.3.pdf Yes]<br />
| [http://membres.lycos.fr/silicium31/Electronique/PIC/ICD2_FW.zip HEX]<br />
|-<br />
| [http://www.nebadje.org/doku.php?id=neblab:icd2clone Nebadje]<br />
| [http://people.ee.ethz.ch/~jbiveron/nebadje/ICD2_DOC.pdf Yes]<br />
| [http://people.ee.ethz.ch/~jbiveron/nebadje/ICD2_FW.zip Zip]<br />
|-<br />
|}<br />
<br />
====Software Interface====<br />
*The program can be written and compiled in an Integrated Development Environment (IDE) using either Assembly or C. The complied codes are then loaded to the device through the external programmer.<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.4 Summary of IDE<br />
! Product Name !! Features !! OS !! Price (US$)<br />
|- <br />
| [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en019469&part=SW007002 MPLAB<sup>®</sup> IDE]<br />
| Assembler Only<br />
| Windows<br />
| Free<br />
|-<br />
| [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en010065&part=SW006012 MPLAB<sup>®</sup> C30]<br />
| Assembler and C-Compiler<br />
| Windows<br />
| $895.00 (Free student version<sup>1</sup>)<br />
|-<br />
| [http://linux.softpedia.com/get/Science-and-Engineering/Electronic-Design-Automation-EDA-/Piklab-8099.shtml Piklab 0.12.0]<br />
| Assembler and C-Compiler<br />
| Linux<br />
| Free<sup>2</sup><br />
|}<br />
# Full-featured for the first 60 days. After 60 days, some code optimization functions are disabled. The compiler will continue to function after 60 days, but code size may increase.<br />
# The current version supports external programmer ICD 2, but not yet tested.<br />
<br />
===RTSP: COM Port (Bootloader)===<br />
*RTSP works in normal voltage (MCLR# no need to raise to V<sub>IHH</sub>).<br />
*No literature has mentioned the incorporation of Programming Executive (PE). Presumably, since Enhanced ICSP needs to set MCLR# to V<sub>IHH</sub>, RTSP cannot use PE.<br />
*Refer to [http://www.opencircuits.com/DsPIC30F_5011_Development_Board#Bootloader_Development bootloader section].<br />
<br />
<br />
==IC Requirements==<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 3.1 IC Requirements<br />
! Part No. !! Description <br />
! Min Temp !! Max Temp !! Min Volt !! Max Volt !! Typ Cur !! Max Cur<br />
|-valign="top"<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/70116F.pdf dsPIC30F5011-30I/PT] || uP <br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 2.5V <sup>[1]</sup>|| 5.5V<br />
| 145mA || 217mA<br />
|-<br />
| [http://datasheets.maxim-ic.com/en/ds/MAX3222-MAX3241.pdf MAX3232ESE] || RS232 driver<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 3.0V || 5.5V<br />
| 0.3mA || 1.0mA<br />
|-<br />
| [http://www.national.com/ds.cgi/DS/DS3695.pdf DS3695N] || RS485 driver<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 4.75V || 5.25V<br />
| 42mA || 60mA<br />
|-<br />
| [http://focus.ti.com/lit/ds/symlink/dac6574.pdf DAC6574IDGS] || 10-bit Quad-DAC I<sup>2</sup>C<br />
| -40<sup>o</sup>C || 105<sup>o</sup>C<br />
| 2.7V || 5.5V<br />
| 0.6mA || 0.9mA<br />
|-<br />
| [http://www.semiconductors.philips.com/acrobat/datasheets/74HC_HCT14_3.pdf 74HC14D] || Quad-Schmitt Trigger<br />
| -40<sup>o</sup>C || 125<sup>o</sup>C<br />
| 2.0V || 6.0V<br />
| || 0.02mA<br />
|-<br />
| '''Overall''' || <br />
| '''-40<sup>o</sup>C''' || '''85<sup>o</sup>C'''<br />
| '''4.75V''' || '''5.25V'''<br />
| || '''<300mA <sup>[2]</sup>'''<br />
|-<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/70165E.pdf dsPIC33FJ128GP306-I/PT] || uP <br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 3.0V <sup>[1]</sup>|| 3.6V<br />
| 74mA || 250mA<br />
|-<br />
| [http://www.analog.com/UploadedFiles/Data_Sheets/ADM3485E.pdf ADM3485EARZ] || RS485 driver<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 3.0V || 3.6V<br />
| 1.1mA || 2.2mA<br />
|-<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/21203N.pdf 24LC256-I/SN] || 256kBits I2C EEPROM<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 2.5V || 5.5V<br />
| 400uA || 3mA<br />
|-<br />
| [http://www.national.com/ds.cgi/LM/LM3940.pdf LM3940IMP-3.3] || 5V-3.3V Regulator<br />
| -40<sup>o</sup>C || 125<sup>o</sup>C<br />
| 5.0V || 7.5V<br />
| 10mA || 250mA<br />
|-<br />
|}<br />
#Minimum voltage measured is 3.3V (with 2 LEDs blinking) running at 30MHz.<br />
#Measured current at 5V is 180mA (with 2 LEDs blinking only)<br />
<br />
<br />
==Development Environment==<br />
<br />
===Windows===<br />
<br />
[[Image:PIC_setup_win.JPG]]<br />
<br />
*C-Compiler, Assembler and Linker are under GNU license.<br />
**MPLAB C30 C Compiler (*.c -> *.s)<br />
**MPLAB ASM30 Assembler (*.s -> *.o)<br />
**MPLAB LINK30 Linker (*.o -> *.bin)<br />
<br />
*PA optimizer, simulator, runtime libraries, header files, include files, and linker scripts are not covered by GNU. Reference is [http://direct.forum.microchip.com/tm.aspx?m=107208 here].<br />
<br />
*Microchip has integrated ASM30, LINK30, assembly header files, linker scripts in MPLAB IDE, which is free for download.<br />
*MPLAB C30 costs US$895. A 60-day free student version is also available. After 60-days, the optimizer is automatically disabled, while other tools can still function properly. Refer to Table 2.4.<br />
<br />
*C-libraries contained in C30 includes (Refer to [http://ww1.microchip.com/downloads/en/DeviceDoc/16bit_Language_Tool_Libraries_51456c.pdf 16-Bit Language Tools Libraries] from Microchip).<br />
<br />
<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 4.1 C Libraries in MPLAB C30<br />
! Library !! Directory <br>(\\Microchip\MPLAB C30) !! Major functions<br />
|-valign="top"<br />
| DSP Library <br>(e.g. libdsp-coff.a)<br />
| \lib <br> \src\dsp <br> \support\h<br />
| Vector, Matrix, Filter, etc.<br />
|-valign="top"<br />
| 16-Bit Peripheral Libraries <br>(e.g. libp30F5011-coff.a)<br />
| \lib <br> \src\peripheral <br> \support\h<br />
| ADC12, IOPort, UART, I<sup>2</sup>C, etc.<br />
|-valign="top"<br />
| Standard C Libraries <br>(e.g. libc-coff.a, libm-coff.a, libpic-coff.a)<br />
| \lib <br> \src\libm <br> \include<br />
| stdio.h, time.h, float.h, math.h, <br />
|-valign="top"<br />
| MPLAB C30 Built-in Functions<br />
| none<br />
| _buildin_addab, _buildin_add, _buildinmpy, etc<br />
|-<br />
|}<br />
<br />
===Linux===<br />
<br />
[[Image:PIC_setup_linux.JPG]]<br />
<br />
*C Compiler, Assembler and Linker are under GNU license.<br />
**The code can be downloaded from Microchip at [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en023073 here].<br />
**Current MPLAB ASM30 Assembler: v2.04<br />
**Current MPLAB C30 Compiler: v2.04<br />
<br />
*[http://gcc.gnu.org/ml/gcc/2005-02/msg01144.html John Steele Scott] has made templates that can be readily used by Debian-based systems. <br />
*For v1.32, the necessary conversion to *.deb has been done already at [http://noel.feld.cvut.cz/dspic/ here].<br />
**Download '''pic30-1.32-debian.tar.bz2''' for Template v1.32.<br />
**Download '''pic30-binutils_1.32-1_i386.deb''' for the assember.<br />
**Download '''pic30-gcc_1.32-1_i386.deb''' for the compiler.<br />
*For v2.00<br />
**goto http://www.baycom.org/~tom/dspic/<br />
**download pic30-gcc-2.00-1.i386.rpm and pic30-binutils-2.00-1.i386.rpm<br />
**convert to deb files<br />
**install these two deb files<br />
*For v3.01, convert the Toolchain following instructions at [http://www.nabble.com/Debian-templates-for-dsPIC-build-toolchain-3.01-tf4308624.html here]<br />
**pre-install these packages: dpkg-dev, debhelper, bison, flex, sysutils, gcc-3.3, fakeroot<br />
**pack pic30-binutils into deb file<br />
**install pic30-binutils<br />
**pack pic30-gcc-3.01 into deb file<br />
**install pic30-gcc-3.01<br />
**pack pic30-support into deb file<br />
**install pic30-support<br />
*'''Important Note''': Only the compiler is free. The header files and library are owned by Microchip. <br />
**Thomas Sailer suggested to download the Student version of C30 compiler and then build the libraries without source code. A package template for Fedora system is available [http://www.baycom.org/~tom/dspic/ here].<br />
**Instructions for filling the upstream direction is available [http://forum.microchip.com/printable.aspx?m=139360 here].<br />
**Alteratively, [https://gna.org/projects/pic30-libc/ Stephan Walter] has started a project to develop C Runtime Library for dsPIC. <br />
***Current libraries in version 0.1.1 include: assert.h, cdefs.h, ctype.h, errno.h, inttypes.h, stdint.h, stdio.h, stdlib.h, string.h<br />
<br />
*Burning Program Codes to Target Board<br />
#Use 'dspicprg and dspicdmp' utilities developed by [http://homerreid.ath.cx/misc/dspicprg/ Homer Reid] to burn hex code (*.hex) to devices. See Reference [http://forum.microchip.com/tm.aspx?m=94243 here]. Through serial port only?<br />
#Use [http://piklab.sourceforge.net/ Piklab IDE]. Details on file format not known.<br />
#Use [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en019469&part=SW007002 MPLAB IDE] to burn hex code (*.hex) to devices.<br />
<br />
===Code Optimization===<br />
*Below is a comparsion between different optimization levels for the project including drivers for 2 projects.<br />
<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 4.2 Comparison between differnt optimization levels<br />
! Optimization !! Description !! Project 1<br>Code Size<br>(byte) !! Project 1<br>Data Usage<br>(byte) !! Project 2<br>Code Size<br>(byte) !! Project 2<br>Data Usage<br>(byte)<br />
|-valign="top"<br />
| O0 <br />
| No optimization<br>Fastest Compilation<br />
| 6222 (9%) || 178 (4%) || 26,037 (38%) || 710 (17%)<br />
|-valign="top"<br />
| O1 <br />
| Optimize<br> Tries to reduce code size and execution time.<br />
| 4473 (6%) || 178 (4%) || 22,290 (32%) || 710 (17%)<br />
|-valign="top"<br />
| O2 <br />
| Optimize even more<br> Performs nearly all supported optimizations <br>that do not involve a space-speed trade-off. <br>Increases both compilation time and the <br>performance of the generated code.<br />
| 4422 (6%) || 178 (4%) || 21,993 (32%) || 710 (17%)<br />
|-valign="top"<br />
| O3 <br />
| Optimize yet more. <br>O3 turns on all optimizations specified by O2 <br>and also turns on the inline-functions option.<br />
| 4485 (6%) || 178 (4%) || 22,176 (32%) || 710 (17%)<br />
|-valign="top"<br />
| Os <br />
| Optimize for size. <br>Os enables all O2 optimizations that do not <br>typically increase code size. It also performs <br>further optimizations designed to reduce code <br>size.<br />
| 4356 (6%) || 178 (4%) || 21,885 (32%) || 710 (17%)<br />
|-<br />
|}<br />
<br />
<br />
==Software Architecture==<br />
+--------+--------+--------+--------+--------+<br />
Application | Task 1 | Task 2 | Task 3 | Task 4 | Task 5 |<br />
+--------+--------+--------+--------+--------+<br />
| POSIX API |<br />
+-------------------+------------------------+<br />
OS | Coroutine | FreeRTOS Scheduler |<br />
+-------------------+------------------------+<br />
| Drivers |<br />
+------+-----+-----+--------+-------+--------+<br />
Hardware | UART | ADC | DAC | EEPROM | PWM | TIMERS | <br />
+------+-----+-----+--------+-------+--------+<br />
*Currently, operating system is based on [http://www.freertos.org/ FreeRTOS] incorporating coroutine developed by [http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html Simon Tatham]<br />
*Software Drivers are to be developed to allow users at Application Level to use the hardware (e.g. ADC, DAC, UART, EEPROM etc) through the OS.<br />
*The interface between the drivers and the OS is based on [http://www.die.net/doc/linux/man/man2/ POSIX standard] (e.g. open(), write(), read(), ioctl(), usleep() etc).<br />
*The most up-to-date development can be found at repository [http://chungyan5.no-ip.org/vc/?root=freertos_posix freertos_posix]<br />
<br />
<br />
==Programming Tips==<br />
<br />
===Memory Map for 5011===<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 6.1 Memory Location<br />
! Type !! Start Address !! End Address !! Size<br />
|-valign="top"<br />
| Flash || 0x000000 ||0x00AFFF || 44K<sup>[1]</sup><br />
|-valign="top"<br />
| +--Flash: Reset Vector || 0x000000 ||0x000003 || 4<br />
|-valign="top"<br />
| +--Flash: Interrupt Vector Table || 0x000004 ||0x00007F || 124<br />
|-valign="top"<br />
| +--Flash: Alternate Vector Table || 0x000084 ||0x0000FF || 124<br />
|-valign="top"<br />
| +--Flash: User Program || 0x000100 ||0x00AFFF || 43.7K<br />
|-valign="top"<br />
| EEPROM || 0x7FFC00 || 0x7FFFFF || 1K<sup>[2]</sup><br />
|-valign="top"<br />
| Programming Executive || 0x800000 || 0x8005BF || 1472<br />
|-valign="top"<br />
| Unit ID || 0x8005C0 || 0x8005FF || 64<br />
|-valign="top"<br />
| Config Registers || 0xF80000 || 0xF8000F || 16<br />
|-valign="top"<br />
| Device ID || 0xFF0000 || 0xFF0003 || 4<br />
|-<br />
|}<br />
[1] Each address is 16-bit wide. Every two addresses correspond to a 24-bit instruction. Each even address contains 2 valid bytes; each odd address contains 1 valid byte plus 1 phathom byte.<br><br />
[2] Each address is 8-bit wide.<br />
<br />
===Data Location===<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 6.2 Data Location<br />
! Type !! Description !! Example<br />
|-valign="top"<br />
| _XBSS(N) <sup>[1]</sup><br />
| RAM Data in X-memory, aligned at N, no initilization<br />
| int _XBSS(32) xbuf[16];<br />
|-valign="top"<br />
| _XDATA(N) <sup>[1]</sup><br />
| RAM Data in X-memory, aligned at N, with initilization<br />
| int _XDATA(32) xbuf[] = {1, 2, 3, 4, 5};<br />
|-valign="top"<br />
| _YBSS(N) <sup>[1]</sup><br />
| RAM Data in Y-memory, aligned at N, no initilization<br />
| int _YBSS(32) ybuf[16];<br />
|-valign="top"<br />
| _YDATA(N) <sup>[1]</sup><br />
| RAM Data in Y-memory, aligned at N, with initilization<br />
| int _YDATA(32) ybuf[16] = {1, 2, 3, 4, 5};<br />
|-valign="top"<br />
| __attribute__((space(const)))<br />
| Flash ROM data, constant, accessed by normal C<br>statements, but 32K max.<br />
| int i __attribute__((space(const))) = 10;<br />
|-valign="top"<br />
| __attribute__((space(prog)))<br />
| Flash ROM data, read/write by program space visibility<br>window (psv)<br />
| int i __attribute__((space(prog)));<br />
|-valign="top"<br />
| __attribute__((space(auto_psv)))<br />
| Flash ROM data, read by normal C statements, write<br>by accessing psv<br />
| int i __attribute__((space(auto_psv)));<br />
|-valign="top"<br />
| __attribute__((space(psv)))<br />
| Flash ROM data, read/write by (psv)<br />
| int i __attribute__((space(psv)));<br />
|-valign="top"<br />
| _EEDATA(N) <sup>[1]</sup><br />
| ROM Data in EEPROM, aligned at N, read/write with psv<br />
| int _EEDATA(2) table[]={0, 1, 2, 3, 5, 8};<br />
|-valign="top"<br />
| _PERSISTENT<br />
| RAM Data, data remain after reset<br />
| int _PERSISTENT var1, var2;<br />
|-valign="top"<br />
| _NEAR<br />
| RAM Data at near section<br />
| int _NEAR var1, var2;<br />
|-valign="top"<br />
| _ISR<br />
| Interrupt service rountine<br />
| void _ISR _INT0Interrupt(void);<br />
|-valign="top"<br />
| _ISRFAST<br />
| Fast interrupt service rountine<br />
| void _ISRFAST _T0Interrupt(void);<br />
|-<br />
|}<br />
#N must be a power of two, with a minimum value of 2.<br />
<br />
===Configuration Bits===<br />
----<br />
*System clock source can be provided by:<br />
#Primary oscillator (OSC1, OSC2)<br />
#Secondary oscillator (SOSCO and SOSCI) with 32kHz crystal<br />
#Internal Fast RC (FRC) oscillator at 7.37MHz (7372800Hz)<br />
#Low-Power RC (LPRC) oscillator (Watchdog Timer) at 512 kHz.<br />
*These clock sources can be incorporated with interal Phase-locked-loop (PLL) x4, x8 or x16 to yield the osciallator frequrence F<sub>OSC</sub><br />
*The system clock is divided by 4 to yield the internal instruction cycle clock, F<sub>CY</sub>=F<sub>OSC</sub>/4<br />
*FRC with PLLx16 is used to achieve F<sub>CY</sub>=29.49MHz (29491200Hz or 30MIPS)<br />
<br />
//The code (MACRO) below is to be placed at the top of program (before main)<br />
_FOSC(CSW_FSCM_OFF & FRC_PLL16);<br />
_FWDT(WDT_OFF); //Turn off Watchdog Timer<br />
_FBORPOR(PBOR_ON & BORV_27 & MCLR_DIS & PWRT_16);<br />
_FGS(CODE_PROT_OFF); //Disable Code Protection<br />
<br />
===Timer===<br />
<br />
----<br />
*Each timer is 16-bit (i.e. counting from 0 to 65535).<br />
*Timer 2 and 3 can be incorporated together to form a 32-bit timer.<br />
*Prescale is the ratio between timer counts and system clock counts. Prescales of 1:1, 1:8, 1:64 and 1:256 are available.<br />
*Timers may be used to implement free time clock or mesaure time.<br />
<br />
====Free Time Clock====<br />
*Let required time for ticking be PERIOD.<br />
*Number of instruction cycles during PERIOD = PERIOD*F<sub>CY</sub> cycles<br />
*Using a prescale of 1:x, the timer period count register = # of cycles/x<br />
*e.g. PERIOD = 10ms; # of cycles = 10ms*30MHz = 300000 cylces; Using 1:64 Prescale, register setting = 300000/64 = 4688<br />
void time_init(void){<br />
TMR1 = 0; // Clear register<br />
PR1 = 4688; // Set period<br />
//============================================================<br />
_T1IF = 0; // Clear interrupt flag<br />
_T1IE = 1; // Enable interrupts<br />
//============================================================<br />
T1CONbits.TCS = 0; // Use internal clock source<br />
T1CONbits.TCKPS = 2; // Prescale Select 1:64<br />
T1CONbits.TON = 1; // Start the timer <br />
}<br />
//********************************************************************<br />
void _ISRFAST _T1Interrupt(void){<br />
_T1IF = 0; // Clear interrupt flag<br />
//Place user code here<br />
}<br />
<br />
====Time Measurement====<br />
*To measure the time taken for action(), use the code below:<br />
unsigned int measure_time(void){ <br />
PR3 = 0xFFFF; // Set counter to maximum<br />
_T3IF = 0; // Clear interrupt flag<br />
_T3IE = 0; // Disable interrupt<br />
T3CONbits.TON = 1; // Start the timer, TMR3 count up<br />
TMR3 = 0; //Clear TMR3 to start count up<br />
//====================================================<br />
//Add code here to wait for something to happen<br />
action();<br />
//====================================================<br />
T3CONbits.TON = 0; //Stop the timer<br />
//====================================================<br />
return (unsigned int) TMR3/FCY; //TMR/FCY yields the actual time<br />
}<br />
<br />
===Interrupt===<br />
<br />
----<br />
*Registers are involved in Interrupts includes: <br />
#Interrupt Flag Status (IFS0-IFS2) registers<br />
#Interrupt Enable Control (IEC0-IEC2) registers<br />
#Interrupt Priority Control (IPC0-IPC10) registers<br />
#Interrupt Priority Level (IPL) register<br />
#Global Interrupt Control (INTCON1, INTCON2) registers<br />
#Interrupt vector (INTTREG) register<br />
*User may assign priority level 0-7 to a specific interrupt using IPC. Setting priority to 0 disable a specific interrupt. Level 7 interrupt has the highest priority.<br />
*Current priority level is stored in bit<7:5> of Status Register (SR). Setting Interrupt Priority Level (IPL) to 7 disables all interrupts (except traps). <br />
*sti() and cli() can be defined to enable and disable global interrupts for time critical functions:<br />
#define IPL ( 0x00e0 )<br />
#define cli() SR |= IPL //Set IPL to 7<br />
#define sti() SR &= ~IPL //Set IPL to 0<br />
//============================================================<br />
char adc_ioctl(unsigned char request, unsigned char* argp){<br />
//...<br />
cli(); //Disable global interrupt<br />
for(;ch<=argp[0];ch++)<br />
adc_add_ch(argp[ch]); //Add adc channels<br />
sti(); //Enable global interrupt<br />
//...<br />
return 0;<br />
}<br />
*dsPic30F has an [http://ww1.microchip.com/downloads/en/DeviceDoc/80223D.pdf errate note] on the Interrupt Controller. When Nested Interrupt is turned on (NSTDIS=0 by default), a high priority interrupt negating a low priority interrupt may result in an Address Error.<br />
*To work around the problem, it is suggested by Microchip to use the following MACRO to protect:<br />
# the clearing of Interrput Flag<br />
# the disabling of Interrupt Enable<br />
# the lowering of Interrupt Priority <br />
# the modification of IPL in Status Register to 1-6<br />
#define DISI_PROTECT(X) { \<br />
__asm__ volatile ("DISI #0x1FFF");\<br />
X; \<br />
DISICNT = 0; \<br />
}<br />
*For example,<br />
void _ISR _T1Interrupt( void )<br />
{<br />
DISI_PROTECT(IFS0bits.T1IF = 0);<br />
//do something here...<br />
}<br />
<br />
===UART===<br />
<br />
----<br />
*5011 provides two UART channels UxART, for x=1, 2.<br />
*UxMODE, UxSTA, UxBRG are registers used to set the mode, indicate the status, and set the baud rate respectively.<br />
*For UART communications compatiable with RS232 standard, an external driver (e.g. MAX3232ESE) is needed.<br />
*For UART communications compatiable with RS485 standard, an external driver (e.g. DS3695N) is needed.<br />
====Auto baud rate detection====<br />
*The method is provided by [http://www.opencircuits.com/DsPIC30F_5011_Development_Board ingenia bootloader].<br />
*The PC sends a ASCII character 'U' (0x55) to the target board.<br />
*On the first rising edge of the start bit, the target board starts the timer.<br />
*At the fifth rising edge, the timer is stopped, let the count number be ''t_count''. <br />
**The measured period corresponds to 8 bits transmitted at a baud rate ''uxbrg''.<br />
_ _ _ _ _ _<br />
_|S|_|1|_|1|_|1|_|1|_|S|_ (S = Start Bit)<br />
<---------------><br />
Measured Time<br />
*The relationship between ''uxbrg'' and ''TMR'' is<br />
Measured Time (in seconds) = t_count/F<sub>cy</sub><br />
uxbrg = 1/(Measured Time/8)<br />
= 8*F<sub>cy</sub>/t_count<br />
*Since UxBRG is computed by:<br />
UxBRG = (F<sub>cy</sub>/(16*Baudrate)) -1<br />
= (F<sub>cy</sub>/(16*8*F<sub>cy</sub>/t_count)) -1<br />
= t_count/128 -1<br />
*The following is the code for auto baud rate detection for U2ART:<br />
unsigned int uart2_autobaud(void){<br />
U2MODEbits.ABAUD = 1; //Enable Autobaud detect from U2RX (from IC2 if 0)<br />
U2MODEbits.UARTEN = 1; //U2ART enable<br />
//Timer 3 Config==========================================================<br />
PR3 = 0xFFFF; // Set counter to maximum<br />
_T3IF = 0; // Clear interrupt flag<br />
_T3IE = 0; // Disable interrupt<br />
T3CONbits.TON = 1; // Start the timer, TMR3 count up<br />
//Input Capture Config====================================================<br />
IC2CONbits.ICM = 3; //Detect rising <br />
_IC2IF = 0; //Clear interrupt flag<br />
_IC2IE = 0; //Disable interrupt<br />
//Start Auto baud detection===============================================<br />
unsigned int i=0;<br />
cli(); //Disable Global Interrupt<br />
while(!_IC2IF); //1st rising edge detected<br />
TMR3 = 0; //Clear TMR3 to start count up<br />
_IC2IF = 0; //Clear interrupt flag<br />
while(!_IC2IF); //2nd rising edge detected<br />
_IC2IF = 0; //Clear interrupt flag<br />
while(!_IC2IF); //3rd rising edge detected<br />
_IC2IF = 0; //Clear interrupt flag<br />
while(!_IC2IF); //4th rising edge detected<br />
_IC2IF = 0; //Clear interrupt flag<br />
while(!_IC2IF); //5th rising edge detected<br />
_IC2IF = 0; //Clear interrupt flag<br />
T3CONbits.TON = 0; //Stop the timer<br />
sti(); //Enable Global Interrupt<br />
//Compute value for BRG register==========================================<br />
unsigned int time;<br />
time = ((TMR3+0x40)>>7)-1; //+0x40 for rounding<br />
//========================================================================<br />
return time;<br />
}<br />
*For 30MIP, tested speeds of transmission include 9600bps, 19200bps, 28800bps, 38400bps and 57600bps.<br />
====open()====<br />
*The following structures and variables are used as circular buffers for transmit and receive.<br />
struct UART_Rx{<br />
unsigned char wr;<br />
unsigned char rd;<br />
};<br />
struct UART_Tx{<br />
unsigned char wr; <br />
unsigned char rd;<br />
unsigned char tx_complete_flag;<br />
};<br />
struct UART_Rx uart_rx;<br />
struct UART_Tx uart_tx;<br />
unsigned char uart_rx_buf[MAX_UART_RX_BUF];<br />
unsigned char uart_tx_buf[MAX_UART_TX_BUF];<br />
<br />
char uart_open()<br />
{<br />
uart_rx.wr = 0;<br />
uart_rx.rd = 0;<br />
uart_tx.wr = 0;<br />
uart_tx.rd = 0;<br />
uart_tx.tx_complete_flag = 1;<br />
uart2_init();<br />
return 0;<br />
}<br />
<br />
void uart2_init(void){<br />
unsigned int u2brg = 97; <br />
#if(AUTO_BAUD_DECT>0)<br />
u2brg = uart2_autobaud();<br />
#endif<br />
U2BRG = u2brg; <br />
//=================================================================<br />
// Disable U2ART<br />
U2MODEbits.UARTEN = 0; //Disable U2ART module<br />
//=================================================================<br />
// Configure Interrupt Priority<br />
_U2RXIF = 0; //Clear Rx interrupt flags<br />
_U2TXIF = 0; //Clear Tx interrupt flags<br />
_U2RXIE = 1; //Receive interrupt: 0 disable, 1 enable <br />
_U2TXIE = 1; //Transmit interrupt: 0 disable, 1 enable<br />
//=================================================================<br />
// Configure Mode<br />
// +--Default: 8N1, no loopback, no wake in sleep mode, continue in idle mode<br />
// +--Diable autobaud detect<br />
// +--Enable U2ART module<br />
U2MODEbits.ABAUD = 0; //Disable Autobaud detect from U2RX <br />
U2MODEbits.UARTEN = 1; //U2ART enable<br />
//=================================================================<br />
// Configure Status<br />
// +--Default: TxInt when a char is transmitted, no break char<br />
// +--Default: RxInt when a char is received, no address detect, clear overflow<br />
// +--Enable Transmit<br />
U2STAbits.UTXEN = 1; //Tx enable<br />
}<br />
<br />
====write()====<br />
*This function writes a series of bytes to the circular buffer and start transmission.<br />
int uart_write(unsigned char *buf, int count)<br />
{<br />
//If transimt has not completed, return busy<br />
if(uart_tx.tx_complete_flag == 0){<br />
return -1; <br />
}<br />
else{<br />
uart_tx.tx_complete_flag = 0;<br />
}<br />
int next_data_pos;<br />
int byte = 0;<br />
for (; byte<count; byte++) {<br />
next_data_pos = pre_wr_cir254buf( (unsigned char)uart_tx.wr, <br />
(unsigned char)uart_tx.rd, <br />
MAX_UART_TX_BUF); <br />
if (next_data_pos!=255) {<br />
//Valid data is available<br />
uart_tx_buf[uart_tx.wr] = (unsigned char) buf[byte]; //copy the char to tx_buf<br />
uart_tx.wr = next_data_pos; //increment the ptr<br />
} else break;<br />
}<br />
//Raise Interrupt flag to initiate transmission<br />
_U2TXIF = 1; //Start interrupt<br />
return byte; <br />
}<br />
*The interrupt routine reads from the circular buffer and send the data. The uart is opened such that the module will generate an TX Interrupt when it a byte is sent.<br />
void _ISR _U2TXInterrupt(void){<br />
DISI_PROTECT(_U2TXIF = 0); //Clear Interrupt Flag<br />
unsigned char next_data_pos;<br />
next_data_pos = pre_rd_cir254buf( (unsigned char)uart_tx.wr,<br />
(unsigned char)uart_tx.rd, <br />
MAX_UART_TX_BUF);<br />
if (next_data_pos!= 255) {<br />
//Valid Data is available to transmit<br />
U2TXREG = (uart_tx_buf[(unsigned char)uart_tx.rd] & 0xFF); //send next byte...<br />
uart_tx.rd = (unsigned char) next_data_pos; //update rd pointer<br />
} else {<br />
//Transimission has completed<br />
uart_tx.tx_complete_flag = 1; // change to empty of tx<br />
}<br />
}<br />
<br />
====read()====<br />
*The interrupt routine writes to the circular buffer when space is available.<br />
void _ISR _U2RXInterrupt(void){<br />
unsigned char next_data_pos;<br />
if ( U2STAbits.URXDA ){<br />
next_data_pos = pre_wr_cir254buf( uart_rx.wr, uart_rx.rd, MAX_UART_RX_BUF);<br />
if (next_data_pos!=255) {<br />
//If buffer is not full<br />
uart_rx_buf[uart_rx.wr] = (unsigned char) U2RXREG; //Read the data from buffer<br />
uart_rx.wr = next_data_pos;<br />
} <br />
else{<br />
//When buffer is full, still remove data from register, butthe incoming data is lost<br />
next_data_pos = (unsigned char) U2RXREG; //Read the data from buffer<br />
} <br />
}<br />
DISI_PROTECT(_U2RXIF = 0); //Clear the flag<br />
}<br />
*This function reads one byte from the circular buffer.<br />
int uart_read(unsigned char *buf)<br />
{<br />
int next_data_pos;<br />
next_data_pos = pre_rd_cir254buf( uart_rx.wr, uart_rx.rd, MAX_UART_RX_BUF);<br />
//Copy 1 byte when data is available<br />
if (next_data_pos!=255) <br />
{<br />
*buf = uart_rx_buf[uart_rx.rd]; //copy the stored data to buf<br />
uart_rx.rd = next_data_pos; //update the ptr<br />
return 1;<br />
}<br />
//No data can be copied<br />
else<br />
{<br />
return 0;<br />
} <br />
}<br />
<br />
===I<sup>2</sup>C===<br />
<br />
----<br />
*Two lines are devoted for the serial communication. SCL for clock, SDA for data.<br />
*Standard communication speed includes<br />
#Standard speed mode: 100kHz<br />
#Fast speed mode: 400kHz<br />
#High speed mode: 3.4MHz<br />
*dsPIC30f5011 supports standard and fast speed modes. The maximum speed attainable is 1MHz.<br />
*Pull-up resistors are required for both SCL and SDA. Minimum pull-up resistance is given by:<br />
Pull-up resistor (min) = (V<sub>dd</sub>-0.4)/0.003 ...... [See section 21.8 in Family reference manual]<br />
*2.2Kohm is typical for standard speed mode.<br />
*After initiating a start/stop/restart bit, add a small delay (e.g. no operation) before polling the corresponding control bit (hardware controlled).<br />
*After sending a byte and receiving an acknowledgement from the slave device, ensure to change to idle state.<br />
<br />
====open()====<br />
*The following structure is used to record whether special bits are needed to be sent.<br />
typedef union{<br />
unsigned char val;<br />
struct{<br />
unsigned START:1; //start<br />
unsigned RESTART:1; //restart<br />
unsigned STOP:1; //stop<br />
unsigned NACK:1; //not acknowledgment<br />
unsigned :1;<br />
unsigned :1;<br />
unsigned :1;<br />
unsigned :1; <br />
}bits;<br />
} I2C_STATUS;<br />
static I2C_STATUS i2c_status; <br />
<br />
*Initializing I<sup>2</sup>C with default speed I2C_BRG without interrupts.<br />
void i2c_open(void)<br />
{<br />
//Open i2c if not already opened<br />
if(I2CCONbits.I2CEN == 0)<br />
{<br />
_SI2CIF = 0; //Clear Slave interrupt<br />
_MI2CIF = 0; //Clear Master interrupt<br />
_SI2CIE = 0; //Disable Slave interrupt<br />
_MI2CIE = 0; //Disable Master interrupt<br />
I2CBRG = I2C_BRG;<br />
I2CCONbits.I2CEN = 1; //Enable I2C module <br />
i2cIdle(); //I2C bus at idle state, awaiting transimission<br />
i2c_status.val = 0; //clear status flags<br />
}<br />
}<br />
<br />
====ioctl()====<br />
*Use this function before read/write to append special bits before or after the data byte.<br />
char i2c_ioctl(unsigned char request, unsigned char* argp)<br />
{<br />
switch(request){<br />
case I2C_SET_STATUS:<br />
i2c_status.val = *argp;<br />
break;<br />
default:<br />
return -1; //request code not recognised <br />
}<br />
return 0;<br />
}<br />
<br />
====write()====<br />
*This function sends an 8-bit data using the I2C protocol.<br />
Mst/Slv _______ M ____M___ S M ________ <br />
SDA (Data) |S| data |A|S|<br />
|T| |C|T|<br />
|A|XXXXXXXX|K|P|<br />
*Use ioctl() to select whether a start/restart/stop bit is required.<br />
*If slave does not respond after ACK_TIMEOUT, the transmission is considered unsucessful.<br />
int i2c_write(unsigned char *buf)<br />
{<br />
unsigned int count = 0;<br />
if(i2c_status.bits.START)<br />
{<br />
I2CCONbits.SEN = 1; <br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.SEN); //Wait till Start sequence is completed<br />
}<br />
else if(i2c_status.bits.RESTART)<br />
{<br />
I2CCONbits.RSEN = 1; <br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.RSEN); //Wait till Start sequence is completed<br />
}<br />
I2CTRN = *buf; //Transmit register<br />
while(I2CSTATbits.TBF); //Wait for transmit buffer to empty<br />
while(I2CSTATbits.ACKSTAT){<br />
if(++count > ACK_TIMEOUT){<br />
//Slave did not acknowledge, byte did not transmit sucessfully, <br />
//send stop bit to reset i2c<br />
I2CCONbits.PEN = 1;<br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.PEN); //Wait till stop sequence is completed<br />
i2cIdle();<br />
return 0;<br />
}<br />
}<br />
i2cIdle();<br />
if(i2c_status.bits.STOP)<br />
{<br />
I2CCONbits.PEN = 1;<br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.PEN); //Wait till stop sequence is completed<br />
i2cIdle();<br />
}<br />
i2c_status.val = 0; //Clear status<br />
return 1;<br />
}<br />
<br />
====read()====<br />
*This function reads 1 byte from slave using the I2C protocol.<br />
Mst/Slv ____ ___S____ M M _____ <br />
SDA (Data) | data |A|S|<br />
| |C|T|<br />
|XXXXXXXX|K|P|<br />
*Use ioctl() to select whether an ACK/NACK and/or STOP bit is needed to be sent.<br />
int i2c_read(unsigned char *buf)<br />
{<br />
I2CCONbits.RCEN = 1; //Enable Receive<br />
while(I2CCONbits.RCEN);<br />
I2CSTATbits.I2COV = 0; //Clear receive overflow<br />
*buf = (unsigned char) I2CRCV; //Access the receive buffer<br />
I2CCONbits.ACKDT = (i2c_status.bits.NACK)? 1 : 0;<br />
I2CCONbits.ACKEN = 1; //Send Acknowledgement/Not Acknowledgement<br />
i2cIdle(); //I2C bus at idle state, awaiting transimission<br />
if(i2c_status.bits.STOP)<br />
{<br />
I2CCONbits.PEN = 1;<br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.PEN); //Wait till stop sequence is completed<br />
i2cIdle();<br />
}<br />
i2c_status.val = 0; //Clear status<br />
return 1;<br />
}<br />
<br />
====Example====<br />
Mst/Slv _______ M ___M___ M S ____M___ S M ___M___ M S ___S____ M ___S____ M M _____ <br />
SDA (Data) |S| | |A| |A|R| | |A| |A| |N|S|<br />
|T|address|W|C|channelA|C|E|address|R|C| Data H |C| Data L |A|T|<br />
|A|1001111|0|K|00010010|K|S|1001111|1|K|10101010|K|10XXXXXX|K|P|<br />
<br />
/*<br />
* Send start bit, slave address (Write Mode)<br />
*/ <br />
status = I2C_START;<br />
i2c_ioctl(I2C_SET_STATUS, &status);<br />
data = (unsigned char) I2C_SLAVE_ADDR;<br />
i2c_write(&data);<br />
/*<br />
* Send control byte: Channel select<br />
*/<br />
data = (unsigned char) ctrl_byte;<br />
i2c_write(&data);<br />
/*<br />
* Send restart bit, slave address (Read Mode)<br />
*/<br />
status = I2C_RESTART;<br />
i2c_ioctl(I2C_SET_STATUS, &status);<br />
data = (unsigned char) (I2C_SLAVE_ADDR|0x01);<br />
i2c_write(&data);<br />
/*<br />
* Receive High Byte with Acknowledgment<br />
*/<br />
i2c_read(&data);<br />
usr_data.high = (unsigned char) data;<br />
/*<br />
* Receive Low Byte with Not Acknowledgment and stop bit<br />
*/ <br />
status = I2C_NACK | I2C_STOP;<br />
i2c_ioctl(I2C_SET_STATUS, &status);<br />
i2c_read(&data);<br />
usr_data.low = (unsigned char) data;<br />
<br />
===ADC===<br />
<br />
----<br />
*12-bit ADC: (Max 16 Channels)<br />
*Allow a maximum of 2 sets of analog input multiplexer configurations, MUX A and MUX B (Normally use one only).<br />
*A maximum of 200kps of sampling rate when using auto sampling mode.<br />
====open()====<br />
*The following variables are required.<br />
unsigned int adc_buf[ADC_MAX_CH]; //Store most updated data<br />
volatile unsigned int* ADC16Ptr = &ADCBUF0; //Pointer to ADC register buffer, <br />
unsigned char adc_ch_select = 0; //Pointer to channel to be read from<br />
unsigned char adc_data_ready = 0; //Indicate if RAM data is ready for output<br />
*Configuration is highlighted below.<br />
**Interrupt: The ADC module will be set to interrupt when the specified channels are updated.<br />
**I/O: Set the corresponding TRISBX bits (digit i/o config) to input (i.e. = 1), and set corresponding bits in ADPCFG (analog config) to zero.<br />
**Scanning Mode: Scan mode is used. In this mode, the Sample and Hold (S/H) is switched between the channels specified by ADCSSL (Scan select register).<br />
**Reference Voltage for S/H: Only MUX A is used. By default, the negative reference voltage of the S/H is connected to V<sub>REF-</sub>.<br />
**Settings for ADC Operation: For 200kbps operation, the voltage references for the ADC voltage are connected to V<sub>REF+</sub> and V<sub>REF-</sub>. Scan input is enabled, and the module will generate an interrupt when all selected channels have been scanned.<br />
**Sampling Rate: T<sub>AD</sub> refers to the time unit for the ADC clock. To configure the ADC module at 200kbps, the minimum sampling time of 1T<sub>AD</sub> = 334ns is required. ADCS<5:0> in ADCON3 register is used to set the time, which is given by:<br />
ADCS<5:0> = 2(T<sub>AD</sub>/T<sub>CY</sub>)-1 <br />
= 2(334e-9/33.34e-9)-1 <br />
= 19<br />
<br />
char adc_open(int flags)<br />
{<br />
// Configure interrupt<br />
_ADIF = 0; //clear ADC interrupt flag<br />
_ADIE = 1; //enable adc interrupt<br />
// Configure analog i/o <br />
_TRISB0 = 1;<br />
_TRISB1 = 1; <br />
ADPCFG = 0xFFFC; //Enable AN0 (Vref+) and AN1 (Vref-)<br />
// Configure scan input channels <br />
ADCSSL = 0x0003; //0 => Skip, 1 => Scan<br />
// Configure CH0 Sample and Hold for 200kbps<br />
// +-- Use MUX A only<br />
// +-- Set CH0 S/H -ve to VRef-<br />
ADCHSbits.CH0NA = 0;<br />
// ADCCON3:<br />
// +--Auto Sample Time = 1TAD<br />
// +--A/D Conversion Clock Source = system clock<br />
// +--A/D Conversion Clock Select ADCS<5:0>= 2(TAD/TCY)-1<br />
// 200kbps(Sampling frequency)<br />
ADCON3bits.SAMC = ADC_ACQ_TIME; //1TAD for sampling time<br />
ADCON3bits.ADRC = 0; //Use system clock<br />
ADCON3bits.ADCS = ADC_ADCS; //each conversion requires 14TAD<br />
// ADCCON2:<br />
// +--Default: Use MUX A, No splitting of Buffer<br />
// +--Voltage Reference Configuration Vref+ and Vref-<br />
// +--Scan Input Selections<br />
// +--5 samples between interrupt<br />
ADCON2bits.VCFG = 3; //External Vref+, Vref-<br />
ADCON2bits.CSCNA = 1; //Scan input<br />
ADCON2bits.SMPI = 1; //take 2 samples (one sample per channel) per interrupt<br />
// ADCCON1:<br />
// +--Default: continue in idle mode, integer format<br />
// +--Enable ADC, Conversion Trigger Source Auto, Auto sampling on<br />
ADCON1bits.FORM = 0; //[0:integer]; [2 fractional]; [3 siged fractional]<br />
ADCON1bits.SSRC = 7; //auto covert, using internal clock source<br />
ADCON1bits.ASAM = 1; //auto setting of SAMP bit<br />
ADCON1bits.ADON = 1; //Turn on module<br />
return 0;<br />
}<br />
<br />
====read()====<br />
*16 registers (ADCBUF0 -ADCBUF15) are dedicated to store the ADC data between interrupts. However, the data in ADCBUFx does not necessarily correspond to the data taken for channel x. Since the lowest register will always be filled first, when some of the channels are not scanned (i.e. skipped), care must be taken. The following code checks the ADCSSL register for the current scanning channels and moves the data to the corresponding position in *adc_buf.<br />
void _ISR _ADCInterrupt(void){<br />
unsigned int channel = 0;<br />
unsigned int buffer = 0;<br />
for (; channel<ADC_MAX_CH; channel++)<br />
{<br />
if(select(channel)) //Check if channel has been selected<br />
{<br />
adc_buf[channel] = ADC16Ptr[buffer]; //Copy data to adc_buf<br />
buffer++;<br />
}<br />
}<br />
adc_data_ready = 1;<br />
DISI_PROTECT(_ADIF = 0); //Clear adc interrupt<br />
}<br />
<br />
static unsigned char select(unsigned char ch)<br />
{<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
if(ADCSSL & mask)<br />
return 1;<br />
return 0;<br />
}<br />
*User can read from the buffer at anytime to get the most updated analog values.<br />
int adc_read(unsigned int* buf, int count)<br />
{<br />
if(adc_data_ready == 1)<br />
{<br />
int num_channel = count/2; //number of channels to read<br />
unsigned char channel = adc_ch_select; //index for adc_buf<br />
int i = 0; //index for buf<br />
while(i<num_channel && channel<ADC_MAX_CH)<br />
{ <br />
//Loop only for specified number of channel or all channels <br />
buf[i++] = adc_buf[channel++]; //use data in local buffer<br />
while(select(channel)==0)<br />
{ //increment to next valid channel<br />
channel++; <br />
if(channel >= ADC_MAX_CH) break;<br />
}<br />
}<br />
return 2*i;<br />
}<br />
return -1;<br />
}<br />
<br />
====ioctl()====<br />
*This function is used to add or remove channels from the ADC scanning process.<br />
char adc_ioctl(unsigned char request, unsigned char* argp)<br />
{<br />
switch(request)<br />
{<br />
case ADC_ADD_CH:<br />
//ADD channels to current set==========================<br />
cli(); //Disable global interrupt<br />
if(select(argp[0]) == 0){ //If channel not in scan list<br />
adcAdd(argp[0]); //Add individual channel to scan list<br />
adc_data_ready = 0; //First data not ready yet, until interrupt occurs<br />
}<br />
adc_ch_select = argp[0]; //Select current channel for reading<br />
sti(); //Enable global interrupt<br />
break;<br />
case ADC_RM_CH:<br />
//REMOVE channels from current set==========================<br />
cli(); //Disable global interrupt<br />
if(select(argp[0])){ //If channel in scan list <br />
adcRm(argp[0]); //Remove individual channel<br />
adc_ch_select = 0; //Reset to AN0<br />
}<br />
sti(); //Enable global interrupt<br />
break;<br />
default:<br />
return -1; //request code not recognised <br />
}<br />
return 0;<br />
}<br />
*Channels may be added or removed by changing _TRISBX, ADPCFG, ADCSSL and ADCON2bits.SMPI.<br />
void adc_add_ch(unsigned char ch){<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
TRISB = TRISB | mask;<br />
ADCSSL = ADCSSL | mask; <br />
ADPCFG = ~ADCSSL;<br />
ADCON2bits.SMPI++; //take one more sample per interrupt<br />
}<br />
<br />
void adc_rm_ch(unsigned char ch){<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
ADPCFG = ADPCFG | mask;<br />
ADCSSL = ~ADPCFG;<br />
ADCON2bits.SMPI--; //take one less sample per interrupt<br />
}<br />
<br />
===EEPROM===<br />
<br />
----<br />
*5011 has 1024 bytes of EEPROM, readable and writable under normal voltage (5V).<br />
*To use, declare:<br />
unsigned char _EEDATA(2) eeData[1024]={ 0x00, 0x00, 0x00, 0x00, .... }<br />
unsigned int byte_pointer = 0;<br />
====lseek()====<br />
*This function moves the pointer to the desired position before a reading/writing operation is performed.<br />
int eeprom_lseek(int offset, unsigned char whence){<br />
byte_pointer = offset;<br />
return byte_pointer;<br />
}<br />
====read()====<br />
*This function read ''count'' bytes from the eeprom.<br />
int eeprom_read(unsigned char* buf, int count){<br />
int i=0;<br />
for(; i<count && byte_pointer < 1024; i++){<br />
readEEByte( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + byte_pointer, <br />
&buf[i]);<br />
byte_pointer++; //Update global pointer<br />
}<br />
return i; //read i bytes successful <br />
}<br />
*readEEByte() is implemented in assembly code as follows:<br />
.global _readEEByte<br />
_readEEByte:<br />
push TBLPAG ;w0 = base of eeData<br />
mov w0, TBLPAG ;w1 = offset for eeData in byte<br />
tblrdl.b [w1], [w2] ;w2 = pointer to user buffer<br />
pop TBLPAG<br />
return<br />
<br />
====write()====<br />
*This function write ''count'' bytes to eeprom.<br />
int eeprom_write(unsigned char* buf, int count){<br />
char isOddAddr = byte_pointer%2; //current address is odd<br />
char isOddByte = count%2; //number of bytes to write is odd<br />
//=================================================================<br />
unsigned int word_offset = byte_pointer>>1; //div by 2 and round down<br />
int max_write;<br />
max_write = (isOddAddr == 0 && isOddByte == 0) ? (count>>1) : (count>>1)+1;<br />
//=================================================================<br />
unsigned int word_data; //Store word to be written<br />
int byte_wr = 0; //number of bytes written, i.e buffer pointer<br />
int i = 0;<br />
//=================================================================<br />
for(; i<max_write && word_offset<512; i++, word_offset++){<br />
if(i==0 && isOddAddr){<br />
//First byte not used<br />
//============================================save first byte<br />
readEEByte( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + byte_pointer - 1,<br />
&word_data);<br />
//===========================================================<br />
word_data = ((unsigned int)buf[0] << 8) + (0xFF & word_data);<br />
byte_wr++; //Update buffer pointer<br />
byte_pointer++; //Update global pointer<br />
} else if(i==max_write-1 && ((isOddAddr && sOddByte==0)||(isOddAddr==0 && isOddByte))){<br />
//Last byte not used<br />
//=============================================save last byte<br />
readEEByte( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + byte_pointer + 1,<br />
&word_data);<br />
//============================================================<br />
word_data = (word_data << 8) + buf[byte_wr];<br />
byte_wr++; //Update buffer pointer<br />
byte_pointer++; //Update global pointer<br />
} else{<br />
//Both bytes valid<br />
word_data = ((unsigned int)buf[byte_wr+1] << 8) + buf[byte_wr];<br />
byte_wr+=2; //Update buffer pointer<br />
byte_pointer+=2; //Update global pointer<br />
}<br />
//==================================================================<br />
eraseEEWord( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + 2*word_offset);<br />
writeEEWord( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + 2*word_offset,<br />
&word_data);<br />
//==================================================================<br />
}<br />
return byte_wr; //No. of byte written<br />
}<br />
*eraseEEWord and writeEEWord are implemented in assembly.<br />
.global _eraseEEWord<br />
_eraseEEWord:<br />
push TBLPAG <br />
mov w0, NVMADRU ;w0 = base of eeData<br />
mov w1, NVMADR ;w1 = offset for eeData in word<br />
mov #0x4044, w0 <br />
mov w0, NVMCON ;Set to erase operation<br />
push SR ;Disable global interrupts<br />
mov #0x00E0, w0<br />
ior SR<br />
mov #0x55, w0 ;Write the KEY sequence<br />
mov w0, NVMKEY<br />
mov #0xAA, w0 <br />
mov w0, NVMKEY<br />
bset NVMCON, #15 ;Start the erase cycle, bit 15 = WR<br />
nop<br />
nop<br />
L1: btsc NVMCON, #15 ;while(NVMCONbits.WR)<br />
bra L1<br />
clr w0<br />
pop SR ;Enable global interrupts<br />
pop TBLPAG<br />
return<br />
<br />
.global _writeEEWord<br />
_writeEEWord:<br />
push TBLPAG ;w0 = base of eeData<br />
mov w0, TBLPAG ;w1 = offset for eeData in byte<br />
tblwtl [w2], [w1] ;w2 = pointer to user buffer<br />
mov #0x4004, w0 ;Set to write operation<br />
MOV w0, NVMCON<br />
push SR ;Disable global interrupts<br />
mov #0x00E0, w0<br />
ior SR<br />
mov #0x55, w0 ;Write the KEY sequence<br />
mov w0, NVMKEY<br />
mov #0xAA, w0 <br />
mov w0, NVMKEY<br />
bset NVMCON, #15 ;Start the erase cycle, bit 15 = WR<br />
nop<br />
nop<br />
L2: btsc NVMCON, #15 ;while(NVMCONbits.WR)<br />
bra L2<br />
clr w0<br />
pop SR ;Enable global interrupts<br />
pop TBLPAG<br />
return<br />
<br />
===Simple PWM (Output Compare Module)===<br />
<br />
----<br />
<br />
*The PWM module consists of 8 channels using the output compare module of dsPic.<br />
*These channels are locate at pin 46 (OC1), 49 (OC2), 50 (OC3), 51 (OC4), 52 (OC5), 53 (OC6), 54 (OC7), 55 (OC8). These pins are shared with port D.<br />
*The range of PWM freqeuencies obtainable is 2Hz to 15MHz (See Figure 6.3). Suggested range of operation is 2Hz to 120kHz. The relationship between resolution ''r'' and PWM frequency ''f''<sub>PWM</sub> is given by:<br />
f<sub>PWM</sub> = f<sub>CY</sub>/(Prescale*10<sup>rlog(2)</sup>)<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 6.3 Relationship of Resolution and PWM Frequency<br />
! Resolution (bit) !! Prescale=1 !! Prescale=8 !! Prescale=64 !! Prescale=256<br />
|- <br />
|1||15,000,000 ||1,875,000 ||234,375||58,594 <br />
|- <br />
|2||7,500,000 ||937,500 ||117,188 ||29,297 <br />
|- <br />
|3||3,750,000 ||468,750 ||58,594 ||14,648 <br />
|- <br />
|4||1,875,000 ||234,375 ||29,297 ||7,324 <br />
|- <br />
|5||937,500 ||117,188 ||14,648 ||3,662 <br />
|- <br />
|6||468,750 ||58,594 ||7,324 ||1,831 <br />
|- <br />
|7||234,375 ||29,297 ||3,662 ||916 <br />
|- <br />
|8||117,188 ||14,648 ||1,831||458 <br />
|- <br />
|9||58,594 ||7,324 ||916 ||229 <br />
|- <br />
|10||29,297 ||3,662 ||458 ||114 <br />
|- <br />
|11||14,648 ||1,831 ||229||57 <br />
|- <br />
|12||7,324 ||916 ||114 ||29 <br />
|- <br />
|13||3,662 ||458 ||57 ||14 <br />
|- <br />
|14||1,831 ||229 ||29 ||7 <br />
|- <br />
|15||916 ||114 ||14 ||4 <br />
|- <br />
|16||458 ||57 ||7 ||2 <br />
|-<br />
|}<br />
<br />
====open()====<br />
*A timer (either Timer 2 or 3) is needed to determine the pwm period. The following code uses timer 2 for all 8 channels.<br />
void pwm_open(void){<br />
OC1CON = 0; OC2CON = 0; //Disable all output compare modules<br />
OC3CON = 0; OC4CON = 0;<br />
OC5CON = 0; OC6CON = 0;<br />
OC7CON = 0; OC8CON = 0;<br />
//============================================================<br />
TMR2 = 0; // Clear register<br />
PR2 = 0xFFFF; // Set to Maximum<br />
//============================================================<br />
_T2IF = 0; // Clear interrupt flag<br />
_T2IE = 0 // Enable interrupts<br />
//============================================================<br />
T2CONbits.TCS = 0; // Use internal clock source<br />
T2CONbits.TCKPS = 0; // Prescale Select 1:1<br />
//============================================================<br />
T2CONbits.TON = 1; // Start the timer <br />
}<br />
<br />
====ioctl()====<br />
*User should select the channel and set the pwm period using the functions below before issuing the duty cycle:<br />
char pwm_ioctl(unsigned char request, unsigned long* argp){<br />
unsigned int value;<br />
unsigned char mask;<br />
switch(request){<br />
case PWM_SET_PERIOD:<br />
return setPeriodNPrescale(argp[0]);<br />
case PWM_SELECT_CH:<br />
pwm_channel = argp[0];<br />
mask = 0x01 << pwm_channel;<br />
pwm_status = pwm_status | mask;<br />
return 0;<br />
default:<br />
return -1;<br />
}<br />
}<br />
char setPeriodNPrescale(unsigned long value_ns){<br />
unsigned long ans;<br />
unsigned long long numerator = (unsigned long long)value_ns*SYSTEM_FREQ_MHZ;<br />
int index= -1;<br />
unsigned long denominator;<br />
//-------------------------------------------------<br />
do{<br />
denominator = (unsigned long)1000*pwm_prescale[++index];<br />
ans = (unsigned long)(((long double)numerator/denominator) + 0.5) - 1; //round to nearest int<br />
} while(ans > 0x0000FFFF && index < 3);<br />
//-------------------------------------------------<br />
if(ans > 0x0000FFFF)<br />
return -1;<br />
//-------------------------------------------------<br />
T2CONbits.TON = 0; // Turn off the timer<br />
T2CONbits.TCKPS = index; // Change prescale factor<br />
PR2 = (unsigned int) ans; // Set to Maximum<br />
T2CONbits.TON = 1; // Turn on the timer <br />
//-------------------------------------------------<br />
return 0;<br />
}<br />
<br />
====write()====<br />
*User can change the duty cycle using the following functions<br />
int pwm_write(unsigned long* buf){<br />
if((pwm_status & (0x01 << pwm_channel)) == 0){<br />
return -1; //Channel has not been enabled<br />
}<br />
switch(pwm_channel){<br />
case 0:<br />
OC1RS = calcDCycle(buf[0]); OC1R = OC1RS; <br />
OC1CONbits.OCM = 6; //Simple PWM, Fault pin disabled<br />
break;<br />
case 1:<br />
OC2RS = calcDCycle(buf[0]); OC2R = OC2RS; <br />
OC2CONbits.OCM = 6; //Simple PWM, Fault pin disabled<br />
break;<br />
...<br />
case 7:<br />
OC8RS = calcDCycle(buf[0]); OC8R = OC8RS; <br />
OC8CONbits.OCM = 6; //Simple PWM, Fault pin disabled<br />
break; <br />
default:<br />
return -1;<br />
}<br />
return 4;<br />
}<br />
unsigned int calcDCycle(unsigned long value_ns){<br />
unsigned long long numerator = (unsigned long long)value_ns*SYSTEM_FREQ_MHZ;<br />
unsigned int index = T2CONbits.TCKPS;<br />
unsigned long denominator = (unsigned long)1000*pwm_prescale[index];<br />
return (unsigned int)(((long double)numerator/denominator) + 0.5) - 1; //round to nearest int<br />
}<br />
<br />
====Propagration Delay====<br />
*PWM channels sharing the same timer will have their PWM signals synchronised (i.e. the HIGH state of the duty cycle are all triggered together).<br />
*To introduced delay to the PWM signals, the signal from selected channels may be made to pass through a series of inverters (e.g. 74HC14D). This adds propagation delay to the signal.<br />
*However, as propagration delay of logic gates depends on applied voltage, temperature and load capacitance, the accuracy is low and performance is poor. For accurate delay, delay lines may be used, but they are expensive.<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 6.4 Propagation Delay of [http://www.nxp.com/acrobat_download/datasheets/74HC_HCT14_3.pdf Philips 74HC14D]<sup>[1], [2]</sup><br />
! !! 3.3V !! !! !! 5.0V !! !!<br />
|- <br />
! Number of Gates !! A !! B !! C !! A !! B !! C<br />
|- <br />
| 2 <br />
| 21ns (10.5)|| 23ns (11.5)|| 22ns (11.0)<br />
| 15ns (7.5)|| 14ns (7.0)|| 14ns (7.0)<br />
|-<br />
| 4 <br />
| 45ns (11.3)|| 46ns (11.5)|| 46ns (11.5) <br />
| 30ns (7.5)|| 30ns (7.5)|| 30ns (7.5)<br />
|-<br />
| 6 <br />
| 69ns (11.5)|| 70ns (11.7)|| 72ns (12.0) <br />
| 45ns (7.5)|| 46ns (7.7)|| 47ns (7.8)<br />
|- <br />
|}<br />
[1] Data in specification for 4.5V: Typical 15ns, Maximum 25ns<br><br />
[2] Data in specification for 6.0V: Typical 12ns, Maximum 21ns<br />
<br />
===DSP Library===<br />
<br />
----<br />
*Library functions in <dsp.h> include the following categories: <br />
#Vector<br />
#Window<br />
#Matrix<br />
#Filtering<br />
#Transform<br />
#Control<br />
<br />
====Data Types====<br />
*Signed Fractional Value (1.15 data format)<br />
**Inputs and outputs of the dsp functions adopt 1.15 data format, which consumes 16 bits to represent values between -1 to 1-2<sup>-15</sup> inclusive.<br />
**Bit<15> is a signed bit, positive = 0, negative = 1.<br />
**Bit<14:0> are the exponent bits ''e''.<br />
**Positive value = 1 - 2<sup>-15</sup>*(32768 - ''e'')<br />
**Negative value = 0 - 2<sup>-15</sup>*(32768 - ''e'')<br />
*40-bit Accumulator operations (9.31 data format)<br />
**The dsp functions use the 40 bits accumalators during arithmatic calculations.<br />
**Bit<39:31> are signed bits, positive = 0x000, negative = 0x1FF.<br />
**Bit<30:0> are exponent bits.<br />
*IEEE Floating Point Values<br />
**Fractional values can be converted to Floating point values using: '''fo = Fract2Float(fr);''' for fr = [-1, 1-2<sup>-15</sup>]<br />
**Floating point values can be converted to Fractional values using: '''fr = Float2Fract(fo);''' or '''fr = Q15(fo);''' for fo = [-1, 1-2<sup>-15</sup>]<br />
**Float2Fract() is same as Q15(), except having saturation control. When +ve >= 1, answer = 2<sup>15</sup>-1 = 32767 (0x7FFF). When -ve < -1, answer = -2<sup>15</sup> = -32767 (0x8000)<br />
<br />
===Build-in Library===<br />
<br />
----<br />
*Some assembler operators can only be accessed by inline assembly code, for example, <br />
#Manuipulation of accumulators A and B (add, sub, mul, divide, shift, clear, square)<br />
#Bit toggling<br />
#Access to psv (program space visiblity) page and offset<br />
#Access to table instruction page and offset<br />
*Built-in functions are written as C-like function calls to utilize these assembler operators.<br />
<br />
<br />
==Bootloader Development==<br />
<br />
===Concepts===<br />
*Programming with ICSP is useful when the target board is produced in batch. The producer can download a program even when the chip is on the target board.<br />
*However, ICSP requires an external programmer.<br />
*To allow the user to change the program after production but without the need of an external programmer, bootloader becomes useful.<br />
*Bootloader is a small program installed via ICSP. Everytime the device is reset, the bootloader is run first. The bootloader first detects the default serial channel whether the user wishes to download a new program to the device. If so, the bootloader will pause there, and wait for the user to download the hex file from the PC. The hex file is written to the device via RTSP instructions in the bootloader. If a new download is not necessary, the bootloader redirects to the previously installed user's program.<br />
*The disadvantage of bootloaders is that they consume some of the memory of the device.<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 7.1 Free bootloaders for dsPIC<br />
! Developer<br />
! Source<br />
! Platform<br />
! User Guide<br />
! Remarks<br />
|- valign="top"<br />
| [http://www.ingenia-cat.com/index.php?lang=en ingenia]<br />
| [http://www.ingenia-cat.com/download/iBL.s Assembly]<br />
| [http://www.ingenia-cat.com/download/ingeniadsPICbootloader1.1.zip Windows]<br />
| [http://www.ingenia-cat.com/reference/pdf/iBL.UG.V1.2.pdf pdf]<br />
| <br />
*Works for all dsPIC supporting RTSP<br />
*Auto baudrate detection<br />
*Use about 1.15% of the flash memory space (0xAFFF-0xAE00)/(0xAFFF-0x0100)<br />
*Development of Linux platform is underway<br />
*Modification of code for dsPIC30F5011 is successful<br />
|-valign="top"<br />
| [http://www.etc.ugal.ro/cchiculita/software/picbootloader.htm Tiny]<br />
| [http://www.etc.ugal.ro/cchiculita/software/tinybld191.zip Assembly]<br />
| Windows<br />
| [http://www.etc.ugal.ro/cchiculita/software/tinybldusage.htm Web]<br />
| <br />
*By default, only supports 601X, 601X, 401X, 2010<br />
*Smaller code size than ingenia, but not as easy to modify<br />
|-valign="top"<br />
| [http://www.via.si/software/dsPIC_bootloader/ Elektronika]<br />
| [http://www.via.si/software/dsPIC_bootloader/data/ Hex]<br />
| Windows<br />
| [http://www.via.si/software/dsPIC_bootloader/data/README.txt txt]<br />
| <br />
*Only works for dsPIC30F6014 serial port UART2 at baudrate 57600<br />
|-<br />
|}<br />
<br />
===dsPicBootloader===<br />
<br />
*The bootloader developed by ingenia is open source and it has been modified (see below) to suit our development using dsPic30f5011.<br />
*The bootloader (hereafter called dsPicBootloader) employs the following settings:<br />
# Use U2ART channel<br />
# Use FRC, PLL16<br />
# For 5011, the bootloader is located between 0x00AE00 to 0x00AFFE (512bytes). Refer to C:\Program Files\Ingenia\ingeniadsPICbootloader\ibl_dspiclist.xml after installing the GUI interface.<br />
*Changes made to [http://www.ingenia-cat.com/download/iBL.s assembly code] includes:<br />
1. including p30f5011.gld and p30f5011.inc<br />
.include "p30f5011.inc"<br />
2. changing the config code of UART #0x8420 -> #0x8020<br />
; Uart init<br />
mov '''#0x8020''', W0 ; W0 = 0x8020 -> 1000 0000 0010 0000b<br />
mov W0, U2MODE ; Enable UART, AutoBaud and 8N1<br />
clr U2STA<br />
3. changing the start address 0xAE00 - 0x0100 = 0AD00<br />
.equ CRC, W4<br />
.equ ACK, 0x55<br />
.equ NACK, 0xFF<br />
.equ USER_ADDRESS, 0x0100<br />
.equ START_ADDRESS, '''0xAD00''' ; Relative to 0x0100<br />
4. using Internal FRC and PLL16<br />
config __FOSC, CSW_FSCM_OFF & '''FRC_PLL16''' ;Turn off clock switching and<br />
;fail-safe clock monitoring and<br />
;use the Internal Clock as the<br />
;system clock<br />
5. disabling MCLR (optional)<br />
config __FBORPOR, PBOR_ON & BORV_27 & PWRT_16 & '''MCLR_DIS'''<br />
;Set Brown-out Reset voltage and<br />
;and set Power-up Timer to 16msecs<br />
6. changing all the related registers of U1ART to U2ART, all U1XXX => U2XXX<br />
'''U2MODE, U2STA, U2BRG, U2RXREG, U2TXREG'''<br />
7. changing all the related registers of IC1 to IC2, all IC1XXX => IC2XXX<br />
'''IC2CON, #IC2IF, #IC2IE'''<br />
<br />
===dsPicProgrammer (Java-based Multi-Platformed)===<br />
*Ingenia developed a programmer (PC-side) that works only in Windows environment. The project for Linux environment is currently suspended.<br />
*A simple programmer (hereafter called dsPicProgrammer) written in Java based on the library developed by [http://www.rxtx.org/ RXTX] has been developed here. The programmer supports both Linux and Windows environments, and may be used as a substitution for the official programmer developed by ingenia.<br />
*The programmer has the following specification and limitations:<br />
#Can be used on both Linux and Windows platforms.<br />
#Adjustable baudrate (9600bps to 57600bps).<br />
#Support programming of dsPIC30F5011 and dsPIC33FJ128GP306 devices (Developers may add your devices).<br />
#Protection against overwriting bootloader codes on devices.<br />
#Detection if application program does not have its reset() at user's code start address.<br />
#Reprogramming can be done without powering down the target board, provided the user's program is compliant to that stated below.<br />
#Target board will run the user's program after programming is done.<br />
#Can be used with USB-Serial Cables. Below is a list of tested cable:<br />
::[http://www.prolific.com.tw/eng/Products.asp?ID=59 Prolific PL-2303 USB to Serial Bridge Controller]: [http://www.prolific.com.tw/eng/downloads.asp?ID=31 Driver download]<br />
<br />
===Special Consideration===<br />
*The bootloader assumes that the user program starts at address 0x100. This is usually the case, but there are always exceptions.<br />
*To ensure that the user program always starts at address 0x100, you can create a customized linker script and customized reset() function as follows:<br />
:*Copy and modify the file named "crt0.s" from the directory "C:\Program Files\Microchip\MPLAB C30\src\pic30" to the project directory and include it.<br />
.section .reset, code //previously .section .libc, code <br />
:*Copy and modify the linkerscript for the device (e.g. p30f5011.gld) to the project directory and include it.<br />
.text __CODE_BASE :<br />
{<br />
*(.reset); //<-insert this line here<br />
*(.handle);<br />
*(.libc) *(.libm) *(.libdsp); /* keep together in this order */<br />
*(.lib*);<br />
*(.text);<br />
} >program<br />
<br />
===Communication Protocol===<br />
<br />
+-------------------+ +-------------------+----------------+<br />
| dsPicProgrammer | | dsPicBootloader | User's Program |<br />
+-------------------+ +-------------------+----------------+<br />
| PC | | Target dsPic |<br />
+-------------------+ +------------------------------------+<br />
| COM PORT |=============| UART |<br />
+-------------------+ +------------------------------------+<br />
<br />
* '''Stage 1: User's Configuation'''<br />
**Select a COM port channel<br />
**Select a baudrate<br />
**Select the user hex file<br />
java -jar dsPicProgrammer.jar COM1 19200 foo.hex<br />
* '''Stage 2: Resetting Target Device'''<br />
**dsPicProgrammer sends a Break character (pull UART-TX to low logic, which is normally high).<br />
**User's program on dsPic detects the break character and reset the chip<br />
::NOTE: The user's program is expected to have the following code in order to enable this function. Otherwise, the target board must be restarted manually.<br />
void _ISR _U2RXInterrupt(void)<br />
{<br />
//No Framming error<br />
if( U2STAbits.FERR == 0)<br />
{<br />
//Normal procedure<br />
}<br />
//Framming error<br />
else<br />
{<br />
if ( U2STAbits.URXDA ){<br />
unsigned char data;<br />
data = (unsigned char) U2RXREG;<br />
if(data == 0x00){<br />
// A break char has been received: <br />
// U2RX has been pulled to zero for more than 13 bits<br />
// This is used to reboot the pic<br />
mdelay(800); //wait for break character to clear<br />
asm("reset"); //software reset<br />
}<br />
} <br />
}<br />
_U2RXIF = 0; //Clear the flag<br />
}<br />
* '''Stage 3: Entering Ingenia's Protocol'''<br />
** Transmission is conducted in 8N1, i.e. 8-bit, no parity, 1 stop-bit<br />
** Communication Protocol is reviewed in [http://www.ingenia-cat.com/reference/pdf/iBL.UG.V1.2.pdf ingenia bootloader user's guide] section 2.1.3. The following summarises the key steps on the PC side (Refer also to section 2.2.2).<br />
::#Autobaud rate detection: dsPicProgrammer continuously sends a character "U" [0x55] via COM port and waits for an acknowledgment character "U", [ACK] = [0x55]<br />
::#Version Control: dsPicProgrammer sends the command character [0x03]. On success, dsPicProgrammer receives 3 characters i) Major Version ii) Minor Version iii) Acknowledgment [0x55]<br />
::#Device ID Monitoring: dsPicProgrammer sends the read command character [0x01] + 24-bit address [High][Medium][Low] (0xFF0000). Then, it receives 4-byte data [High][Medium][Low][ACK]<br />
::#Load the user hex file and check integrity<br />
::#Start Programming: dsPicProgrammer issues the write command character [0x02] + 24-bit address [High][Medium][Low]+ Number of bytes [N] + [data 0] + [data 1] + ... + [data N-1] + [CRC]=(INTEL HEX8 Checksum - Sum modulo 256) and receives [ACK] or [NACK] = [0xFF]<br />
::NOTE: Writing is in row mode access (i.e. erase and write a whole row, each row has 32 instructions, or 96 bytes because each instruction has 24 bits)<br />
* '''Stage 4: Goto User's Program'''<br />
**dsPicProgrammer sends the goto user code command [0x0F]<br />
<br />
<br />
==USB-RS232 Bridge==<br />
<br />
*As USB ports are becoming more and more common, COM ports and Parallel ports may be redundant in the next few years. This section explore the possibilities of programming the target board through a USB port.<br />
*There are two options:<br />
#Use an external USB/RS232 adaptor, the driver will emulate a virtual COM port, such as [http://www.prolific.com.tw/eng/downloads.asp?ID=31 Prolific] and [http://www.ftdichip.com/Drivers/VCP.htm FDTI]. Ingenia has tested its bootloader with some USB-232 manufacturers (silabs, FTDI, etc..). However, the programming failed with our Prolific adapter. Application program may use [http://java.sun.com/products/javacomm/ JavaComm API] (javax.comm) and/or [http://www.rxtx.org/ RXTX] to drive the COM port.<br />
#Modified the bootloader program on PC to support USB communication. e.g. using [http://jusb.sourceforge.net/ jUSB] and [http://javax-usb.org/ JSR-80] (javax.usb). External circuits such as PIC18F4550 and MAX232 are required.<br />
<br />
|--User's App.--|-------Device Manager------|-------USB-RS232 Interface------|---dsPIC---|<br />
Option 1:<br />
+-------------+ +----------+ +----------+ +---+ +------------+ +-----+ +--------+<br />
| Application |--| JavaComm |--| Virtual |==|USB|--| FDTI |--|RS232|==| Target |<br />
| Program | | RXTX | | COM Port | +---+ | Circuitary | +-----+ | Board |<br />
+-------------+ +----------+ +----------+ +------------+ +--------+<br />
Option 2:<br />
+-------------+ +--------+ +---+ +------------+ +-----+ +--------+<br />
| Application |----------| JSR-80 |==========|USB|--| PIC18F4550 |--|RS232|==| Target |<br />
| Program | | jUSB | +---+ | MAX232 | +-----+ | Board |<br />
+-------------+ +--------+ +------------+ +--------+<br />
<br />
*Currently, when RXTX is incorporated with JavaComm API, operating systems supported include Linux, Windows, Mac OS, Solaris and other operating systems. On the other hand, jUSB and JSR-80 only works for linux.<br />
<br />
===FDTI Chipset===<br />
*FT232RL communicates with PC via USB to provide 1 UART channel.<br />
*Datasheet can be downloaded [http://www.ftdichip.com/Documents/DataSheets/DS_FT232R.pdf here]. <br />
**Refer to Fig. 11 (Page 19) for Bus Powered Configuration.<br />
**Refer to Fig. 16 (Page 24) for for UART TTL-level Receive [RXD -> 1], Transmit [TXD -> 4], Transmit Enable [CBUS2/TXDEN -> 3]. Omit Receive Enable [CBUS3/PWREN#] and use [CBUS2/TXDEN -> 2] <br />
**Refer to Fig. 15 (Page 23) for LED Configuration: [CBUS0/TXLED#] and [CBUS1/RXLED#]<br />
*Virtual COM Port Drivers can be downloaded [http://www.ftdichip.com/Drivers/VCP.htm here].<br />
<br />
<br />
==Programming the Device==<br />
<br />
===Requirements===<br />
*Hardware<br />
#PC with COM port (Windows XP Installed for MPLAB)<br />
#ICD2 Programmer<br />
#Target Board<br />
#5V Power Supply<br />
<br />
*Software<br />
#[http://ww1.microchip.com/downloads/en/DeviceDoc/MP750.zip MPLAB IDE v7.50]: v7.60 is not compatible with our current [http://www.sure-electronics.com/ ICD2 Programmers]. There are consistent "Devices cannot be founded" warnings.<br />
#[http://chungyan5.no-ip.org/websvn/listing.php dsPicProgrammer] ('''dsPicProgrammer.jar''')<br />
#[http://users.frii.com/jarvi/rxtx/download.html RXTX driver]: download and upzip rxtx-2.1-7-bins-r2.zip (Final)<br />
<br />
*Files<br />
#[http://chungyan5.no-ip.org/websvn/listing.php dsPicBootloader] ('''bl_5011.hex'''). Original assembly code by ingenia can be downloaded from [http://www.ingenia-cat.com/download/iBL.s here].<br />
#Application hex file (e.g. '''app.hex''')<br />
<br />
===Loading Bootloader (Once only)===<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 9.1 Loading Bootloader<br />
! Step !! Remarks <br />
|-valign="top"<br />
| Install [http://ww1.microchip.com/downloads/en/DeviceDoc/MP750.zip MPLAB IDE] || <br />
*Do '''NOT''' connect ICD 2 (via USB) to PC<br />
*Execute '''MPLAB vX.XX Install.exe'''<br />
|-valign="top"<br />
| Install USB Driver ||<br />
*Follow the instruction in (C:\Program Files\Microchip\MPLAB IDE\ICD2\Drivers\Ddicd2.htm)<br />
|-valign="top"<br />
| Select Target Chip ||<br />
*Run MPLAB IDE on PC<br />
*Select: Configure>Select Devices...<br />
*Choose dsPIC30F5011<br />
|-valign="top"<br />
| Target <-> ICD 2 ||<br />
*Use six pin cable. Beware of the pin assignments. Only pin 1 - 5 should be used.<br />
*Place Jumper on target board (if any). The Jumper connects target V<sub>cc</sub> to ICD 2.<br />
*Do '''NOT''' power-up the target.<br />
|-valign="top"<br />
| ICD 2 <-> PC ||<br />
*Plug-in ICD 2 to PC via USB cable<br />
*Power-up the target.<br />
*Select: Programmer>Select Programmer>MPLAB ICD 2<br />
*If this is the first time the ICD 2 is connected to PC, MPLAB IDE will automatically download the required OS to ICD 2, wait until it has finished<br />
*If you have not connected and powered up the target, you might see Warnings on invalid device IDs, and/or running self tests.<br />
*See results of self test if necessary: Programmer>Settings, Status Tab. Refer to [http://ww1.microchip.com/downloads/en/DeviceDoc/51331B.pdf ICD2 User's Guide] Chapter 7.<br />
|-valign="top"<br />
| Load Bootloader ||<br />
*Select: File>Import...<br />
*Select '''bl_5011.hex'''<br />
|-valign="top"<br />
| Start Programming ||<br />
*Select: Programmer>Program<br />
|-valign="top"<br />
| Finishing ||<br />
*Power-down the Taget<br />
*Select: Programmer>Select Programmer>None<br />
*Unplug USB cable<br />
|-<br />
|}<br />
<br />
===Loading Firmware===<br />
====Java Environment Setup====<br />
*Download and install the latest JDK or JRE<br />
**Available from [http://java.sun.com/javase/downloads/index.jsp Sun Microsystems] (e.g. JDK 6 Update 3)<br>[[Image:1 1 java.JPG]]<br><br />
*Download and Extract RXTX Driver <br />
**Available from [http://users.frii.com/jarvi/rxtx/download.html RXTX] <br />
**File: rxtx-2.1-7-bins-r2.zip (Final)<br />
**Extract the files using software such as WinRAR<br>[[Image:1 2 rxtx.JPG]]<br><br />
*Copy RXTXcomm.jar<br />
**To C:\Program Files\Java\X\lib\ext (under the latest jre, e.g. X = jre1.6.0_03)<br>[[Image:1 3 rxtxcomm.JPG]]<br><br />
*Copy rxtxSerial.dll<br />
**To C:\Program Files\Java\X\bin (under the lastest jre, e.g. X = jre1.6.0_03)<br />
**For Linux users, copy librxtxSerial.so to /jre/lib/[machine type] (i386 for instance)<br>[[Image:1 4 rxtxserial.JPG]]<br><br />
*Download dsPicProgrammer <br />
**Available from [http://chungyan5.no-ip.org/websvn/listing.php?repname=repos+1&path=%2FdsPicProgrammer%2Ftags%2F&rev=0&sc=0 here]<br />
**Expand the latest tag under dsPicProgrammer<br />
**File: dsPicProgrammer.jar<br>[[Image:1 5 dspicprogrammer.JPG]]<br><br />
**Save the file (dsPicProgrammer.jar) and your hex file (foo.hex) to your local directory (e.g. C:\dsPicProgrammer\)<br>[[Image:1 6 dspicprogrammer2.JPG]]<br><br />
<br />
====Download Firmware====<br />
*Start a Command Prompt<br />
**Start -> Run<br>[[Image:2 1 run.JPG]]<br><br />
**Enter cmd<br>[[Image:2 2 cmd.JPG]]<br><br />
*Run dsPicProgrammer<br />
**Change to the directory where dsPicProgrammer.jar is located and run the command:<br>java -jar dsPicProgrammer.jar COM1 57600 foo.hex (Windows)<br>java -jar dsPicProgrammer.jar /dev/ttyS0 57600 foo.hex (Linux)<br>where COM1 is your COM Port ID<br>57600 is communication speed [in bps]<br>foo.hex is your firmware new file<br>[[Image:2 3 command.JPG]]<br><br />
**When the program prompt you for an input, press y:<br>[[Image:2 4 prompt.JPG]]<br><br />
**If communication can be established, you should see something like this:<br>[[Image:2 5 progress.JPG]]<br><br />
**Wait until programming is completed.<br>[[Image:2 6 complete.JPG]]<br><br />
**after all completed, power OFF your device, then power ON again, enjoy your new updated.<br />
<br />
====Troubleshooting====<br />
*Invalid COM Port<br />
**In case of selecting an invalid COM port, you should see the error message:<br>gnu.io.NoSuchPortException: Choosing COM Port Error<br>[[Image:3 1 com err.JPG]]<br><br />
*Missing firmware file<br />
**In case of selecting a firmware file that does not exist, you should see the error message:<br>java.io.FileNotFoundException: foo1.hex <The system cannot find the file specified><br>[[Image:3 2 file err.JPG]]<br><br />
*Missing RXTX driver<br />
**In case of missing the RXTX driver, you should see the error message:<br>Exception in thread “main” java.lang.NoClassDefFoundError: gnu/io/UnsupportedCommOperationException<br>[[Image:3 3 rxtx err.JPG]]<br><br />
<br />
<br />
==Remote Access==<br />
*At the moment, local devices (e.g. EEPROM, ADC, DAC, etc.) can only be accessed locally through POSIX functions such as open(), read(), write(), ioctl().<br />
*However, a client may need to access these devices on a remote server. This section reviews the background and gives some ideas on its possible implementation.<br />
<br />
===Requirements===<br />
*A remote file access protocol, to transfer "files" (i.e. device's data) such as:<br />
#[http://en.wikipedia.org/wiki/FTP File Transfer Protocol] (FTP): Required files are copied from sever to client for manipulation<br />
#[http://en.wikipedia.org/wiki/Remote_Shell Remote Shell] (RSH): Required files are copied from sever to client for manipulation<br />
#[http://en.wikipedia.org/wiki/Network_File_System_%28Sun%29 Network File System] (NFS): Required files are manipulated on sever<br />
*An API to access files using a selected protocol, such as:<br />
#[http://www.die.net/doc/linux/man/man2/lam_rfposix.2.html lam_rfposix]: A POSIX-like remote file service for Local Area Multicomputer<br />
#API employed by VxWorks: [http://en.wikipedia.org/wiki/VxWorks VxWorks] is a Unix-like real-time operating system, commonly used for embedded systems.<br />
<br />
===API Reference for VxWorks===<br />
*Reference:<br />
**[http://www.windriver.com/vxworks/ VxWorks Official Website]<br />
**[http://www-cdfonline.fnal.gov/daq/commercial/ OS Libraries API Reference]<br />
*Related Libraies<br />
**netDrv (netDrv.h): an API using FTP or RSH<br />
**nfsDrv (nfsDrv.h): an API using NFS<br />
<br />
<br />
==Conversion to dsPIC33F Devices==<br />
*This section discusses the conversion required from dsPIC30F5011 to dsPIC33FJ128GP306.<br />
*Refer to official document [http://ww1.microchip.com/downloads/en/DeviceDoc/70172A.pdf dsPIC30F to dsPIC33F Conversion Guidelines] (DS70172A).<br />
*Note that this section does not mainly intend to introduce the new functionalities of dsPIC33F devices. It only serves the purpose to summarise the major (if not minimum) changes required to port the setup of dsPIC30 to dsPIC33 devices.<br />
<br />
===Hardware===<br />
*dsPIC33 operates at voltage of 3.3V. A voltage regulator, such as [http://www.national.com/ds.cgi/LM/LM3940.pdf LM3940] can be used to convert 5V supply to 3.3V.<br />
*A 1uF capacitor has to be placed at pin 56 (previously V<sub>SS</sub>, now V<sub>DDCORE</sub>).<br />
<br />
===Software===<br />
<br />
====Configuration Bits====<br />
<br />
----<br />
*dsPIC33 can operate at 40MIPs at maximum. To configure the device using internal FRC, replace the configuration bits setting as follows:<br />
_FOSCSEL(FNOSC_FRCPLL); // FRC Oscillator with PLL<br />
_FOSC(FCKSM_CSDCMD & OSCIOFNC_ON & POSCMD_NONE); <br />
// Clock Switching and Fail Safe Clock Monitor is disabled<br />
// OSC2 Pin Function: OSC2(RC15) as Digital IO<br />
// Primary Oscillator Mode: Disabled<br />
_FWDT(FWDTEN_OFF); // Watchdog Timer Enabled/disabled by user software <br />
*Configure on-chip PLL at runtime as follows (at start of main function):<br />
_PLLDIV = 38; // M=40: PLL Feedback Divisor bits<br />
CLKDIV = 0; // N1=2: PLL VCO Output Divider Select bits<br />
// N2=2: PLL Phase Detector Input Divider bits<br />
OSCTUN = 22; // Tune FRC oscillator, if FRC is used; <br />
// 0: Center frequency (7.37 MHz nominal)<br />
// 22: +8.25% (7.98 MHz)<br />
RCONbits.SWDTEN = 0; // Disable Watch Dog Timer<br />
while(OSCCONbits.LOCK != 1); // Wait for PLL to lock<br />
<br />
====UART====<br />
<br />
----<br />
*No change is required.<br />
<br />
====I2C====<br />
<br />
----<br />
*dsPIC33 supports upto 2 I<sup>2</sup>C devices. As a result, replace all I<sup>2</sup>C related registers with xxI2Cyy to xxI2C'''1'''yy. For examples:<br />
_SI2C1IF = 0; //Clear Slave interrupt<br />
_MI2C1IF = 0; //Clear Master interrupt<br />
_SI2C1IE = 0; //Disable Slave interrupt<br />
_MI2C1IE = 0; //Disable Master interrupt<br />
I2C1BRG = I2C_BRG; // Configure Baud rate<br />
I2C1CONbits.I2CEN = 1;<br />
...<br />
etc.<br />
<br />
====ADC====<br />
<br />
----<br />
*The ADC in dsPic33 is significantly different from that in dsPic30. Specifically, ADC in dsPic33 uses DMA to buffer the adc data. Replace the open, interrupt routine, add and remove codes as follows:<br />
<br />
unsigned int adc_bufA[ADC_MAX_CH] __attribute__((space(dma),aligned(256)));<br />
unsigned int adc_bufB[ADC_MAX_CH] __attribute__((space(dma),aligned(256)));<br />
unsigned int* ADC16Ptr; //Pointer to ADC register buffer, <br />
unsigned char adc_ch_select = 0; //Pointer to channel to be read from<br />
unsigned char adc_data_ready = 0; //Indicate if RAM data is ready for output<br />
unsigned int which_dma = 0; //indicate which adc_buf to be used<br />
<br />
void adc_open(void)<br />
{<br />
// Configure interrupt<br />
_AD1IF = 0; //clear ADC interrupt flag<br />
_AD1IE = 0; //disable adc interrupt<br />
AD1CHSbits.CH0NA = 0;<br />
// Configure analog i/o <br />
_TRISB0 = 1;<br />
_TRISB1 = 1; <br />
AD1PCFG = 0xFFFC; //Enable AN0 (Vref+) and AN1 (Vref-)<br />
AD1PCFGH = 0xFFFF; //AN16-AN31: Disabled<br />
// Configure scan input channels <br />
AD1CSSL = 0x0003; //0 => Skip, 1 => Scan<br />
AD1CSSH = 0x0000; //Skipping AN16-AN31<br />
// ADCCON4:<br />
AD1CON4bits.DMABL = 0; // Each buffer contains 1 word<br />
// ADCCON3:<br />
AD1CON3bits.SAMC = 1; //1TAD for sampling time<br />
AD1CON3bits.ADRC = 0; //Use system clock<br />
AD1CON3bits.ADCS = ADC_ADCS; //each conversion requires 14TAD<br />
// ADCCON2:<br />
AD1CON2bits.VCFG = 3; //External Vref+, Vref-<br />
AD1CON2bits.CSCNA = 1; //Scan input<br />
AD1CON2bits.SMPI = 1; //2 channels are scanned<br />
// ADCCON1:<br />
AD1CON1bits.FORM = 0; //[0:integer]; [2 fractional]; [3 siged fractional]<br />
AD1CON1bits.SSRC = 7; //auto covert, using internal clock source<br />
AD1CON1bits.ASAM = 1; //auto setting of SAMP bit<br />
AD1CON1bits.AD12B = 1; //12-bit, 1-channel ADC operation<br />
AD1CON1bits.ADDMABM = 0; // DMA buffers are built in scatter/gather mode<br />
AD1CON1bits.ADON = 1; // Turn on the A/D converter<br />
// DMA0 Configuration:<br />
DMA0CONbits.AMODE = 2; // Configure DMA for Peripheral indirect mode<br />
DMA0CONbits.MODE = 2; // Configure DMA for Continuous Ping-Pong mode<br />
DMA0PAD=(int)&ADC1BUF0; <br />
DMA0CNT = 1; // generate dma interrupt every 2 samples <br />
// same as SMPI because only 1 dma buffer per channel <br />
DMA0REQ = 13; // Select ADC1 as DMA Request source<br />
DMA0STA = __builtin_dmaoffset(adc_bufA); <br />
DMA0STB = __builtin_dmaoffset(adc_bufB);<br />
_DMA0IF = 0; // Clear the DMA interrupt flag bit<br />
_DMA0IE = 1; // Set the DMA interrupt enable bit<br />
DMA0CONbits.CHEN=1; // Enable DMA<br />
}<br />
<br />
void _ISR _DMA0Interrupt(void)<br />
{<br />
ADC16Ptr = (which_dma == 0)? adc_bufA : adc_bufB; //Update pointer<br />
adc_data_ready = 1;<br />
which_dma ^= 1; //Next buffer to be used<br />
_DMA0IF = 0; //Clear the DMA0 Interrupt Flag<br />
}<br />
<br />
static void adcAdd(unsigned char ch){<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
TRISB = TRISB | mask;<br />
AD1CSSL = AD1CSSL | mask; <br />
AD1PCFG = ~AD1CSSL;<br />
AD1CON2bits.SMPI++; //take one more sample per interrupt<br />
DMA0CNT++; <br />
}<br />
<br />
static void adcRm(unsigned char ch){<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
AD1PCFG = AD1PCFG | mask;<br />
AD1CSSL = ~AD1PCFG;<br />
AD1CON2bits.SMPI--; //take one less sample per interrupt<br />
DMA0CNT--; <br />
}<br />
<br />
====EEPROM====<br />
<br />
----<br />
*There is no EEPROM in dsPIC33 devices. Please consider to use an external EEPROM using I<sup>2</sup>C communication.<br />
<br />
====Simple PWM====<br />
<br />
----<br />
*No change is required.<br />
<br />
===Memory Map for dsPIC33FJ128GP306===<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 11.1 Memory Location<br />
! Type !! Start Address !! End Address !! Size<br />
|-valign="top"<br />
| Flash || 0x000000 ||0x0157FF || 86K<sup>[1]</sup><br />
|-valign="top"<br />
| +--Flash: Reset Vector || 0x000000 ||0x000003 || 4<br />
|-valign="top"<br />
| +--Flash: Interrupt Vector Table || 0x000004 ||0x0000FF || 252<br />
|-valign="top"<br />
| +--Flash: Alternate Vector Table || 0x000104 ||0x0001FF || 252<br />
|-valign="top"<br />
| +--Flash: User Program || 0x000200 ||0x0157FF || 85.5K<br />
|-valign="top"<br />
| Programming Executive || 0x800000 || 0x800FFF || 4K<sup>[1]</sup><br />
|-valign="top"<br />
| Config Registers || 0xF80000 || 0xF80017 || 24<br />
|-valign="top"<br />
| Device ID (0xE5) || 0xFF0000 || 0xFF0003 || 4<br />
|-<br />
|}<br />
[1] Each address is 16-bit wide. Every two addresses correspond to a 24-bit instruction. Each even address contains 2 valid bytes; each odd address contains 1 valid byte plus 1 phathom byte.<br><br />
<br />
===Custom Linker Script to Maximize Space for Constant Data===<br />
*Constant data declared using keyword '''const''' will be stored in the .const section in the flash memory.<br />
*Normally, during compilation, the linker will assign these data after the program code (.text section).<br />
*Since .const is accessed by auto-psv function, to maximize the space for constant data (32kb), the .const section needs to be aligned at 0x80000 boundary.<br />
*This requires the following change in linker script:<br />
<br />
__CONST_BASE = 0x8000;<br />
<br />
.text __CODE_BASE :<br />
{<br />
*(.reset);<br />
*(.handle);<br />
*(.libc) *(.libm) *(.libdsp); /* keep together in this order */<br />
*(.lib*);<br />
/* *(.text); deleted to maximize space for const data */<br />
} >program<br />
<br />
.const __CONST_BASE :<br />
{<br />
*(.const);<br />
} >program<br />
<br />
*If your program is large, after this change in linker script, function calls may involve large jump in the memory map (>32kB). As a result, you may need to enable the large code and large memory model during compilation. In such case, use the following options in your build path:<br />
-mlarge-code -mlarge-data<br />
*Meanwhile, functions that are defined in the standard C libraries, but are replaced with your own implementations (e.g. I/O stubs: open(), read(), write(), lseek(), ioctl() etc.) may have the following linker error:<br />
/usr/pic30-elf/lib//libc-elf.a(fflush.eo)(.libc+0x3c): In function '.LM11':<br />
: Link Error: relocation truncated to fit: PC RELATIVE BRANCH _write<br />
/usr/pic30-elf/lib//libc-elf.a(fclose.eo)(.libc+0x42): In function '.LM18':<br />
: Link Error: relocation truncated to fit: PC RELATIVE BRANCH _close <br />
*To resolve the problem, you need to place the functions in the .libc section rather than in the .text section, like this:<br />
#define LIBC_CODE_LOC __attribute__ ( (section(".libc")))<br />
<br />
int LIBC_CODE_LOC open(const char *pathname, int flags){ ... }<br />
int LIBC_CODE_LOC close(int fd){ ... }<br />
int LIBC_CODE_LOC write(int fd, void* buf, int count) { ... }<br />
int LIBC_CODE_LOC read(int fd, void* buf, int count) { ... }<br />
int LIBC_CODE_LOC ioctl(int fd, int request, void* argp) { ... }<br />
int LIBC_CODE_LOC lseek(int fd, int offset, int whence) { ... }<br />
<br />
===dsPicBootloader and dsPicProgrammer===<br />
*RTSP for dsPIC33F is different from dsPIC30F.<br />
**Row size changes from 32 instructions (96bytes) to 64 instructions (192 bytes)<br />
**Erase operation changes from 1 row to 8 rows<br />
**No EEPROM<br />
*With regards to the above changes, dsPicBootloader and dsPicProgrammer has been modified. In particular, dsPicProgrammer can be used to program both dsPic30F and dsPic33F devices. You can easily add your devices to the source code.<br />
<br />
<br />
==Downloads==<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 12.1 Related software download links for dsPicBootloader and dsPicProgrammer<br />
! Program<br />
! Site 1<br />
! Site 2<br />
! Remarks<br />
|- valign="top"<br />
| JDK<br />
| [http://java.sun.com/javase/downloads/index.jsp website]<br />
| <br />
| Download latest JDK<br />
|- valign="top"<br />
| RXTX<br />
| [http://users.frii.com/jarvi/rxtx/download.html website]<br />
| <br />
| Download rxtx-2.1-7-bins-r2.zip or later<br />
|- valign="top"<br />
| dsPicBootloader v1.3<br />
| [http://chungyan5.no-ip.org/websvn/listing.php click]<br />
| [http://www.opencircuits.com/images/a/a7/DsPicBootloader_1_3_1.zip click]<br />
| Under "dsPicBootloader/", download bl_5011.s or bl_j128gp306.s<br />
|-valign="top"<br />
| dsPicProgrammer v1.3.5<br />
| [http://chungyan5.no-ip.org/websvn/listing.php click]<br />
| [http://www.opencircuits.com/images/9/9e/DsPicProgrammer_1_3_5.zip click]<br />
| Under "dsPicProgrammer/", dowload dsPicProgrammer.jar<br><br>Alternatively, if you want to compile yourself or modify the source code, download <br>all source files under "dsPicProgrammer/" '''plus''' RdFileIntelHex.java under <br>"IntelHexPaser/tags/0.02.00/".<br>You should also install RXTX on your local machine as recommended in the readme file.<br />
|- valign="top"<br />
| Ingenia's bootloader<br />
| [http://www.ingenia-cat.com/en/downloads.php website]<br />
| <br />
| Download original ingenia's bootloader<br />
|-<br />
|}</div>Yanhttp://www.opencircuits.com/index.php?title=DsPIC30F_5011_Development_Board&diff=13152DsPIC30F 5011 Development Board2008-01-16T09:00:47Z<p>Yan: /* Java Environment Setup */ morfe shortcut to Dspic Java Programmer</p>
<hr />
<div>==Introduction==<br />
<br />
===Features of dsPIC30F5011===<br />
*2.5 to 5V <br />
*Up to 30MIPs<br />
*High current/sink source I/O pins: 25mA<br />
*DSP Instruction Set<br />
*Dual programming techniques: ICSP and RTSP<br />
*UART: up to 2 modules<br />
*I<sup>2</sup>C: up to 1Mbps<br />
*10-bit A/D, 1.1 Msps <br />
*12-bit A/D, 200 ksps<br />
*44K flash (66Kb), 4Kb RAM, 1Kb EEPROM<br />
*No DAC<br />
*Pin-to-pin compatible with other dsPICs<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 1.1 Comparison with Compatible dsPICs<br />
! dsPic !! Price<br>US$ !! MIPs<br />
! Flash<br>(kB)!! RAM<br>(kB) !! EEPROM<br>(kB)<br />
! I/O !! ADC<br>12-bit !! IC !! OC !! Motor<br>Ctrl !! Timers<br />
! QEI !! UART !! SPI !! I2C !! CAN !! Codec<br />
|- <br />
| 30F5011 || 5.91 || 30<br />
| 66 || 4 || 1<br />
| 52 || 16 || 8 || 8 || 0 || 5x16bit<br>2x32bit<br />
| 0 || 2 || 2 || 1 || 2 || 1<br />
|-<br />
| 30F6011A || 7.73 || 30<br />
| 132 || 6 || 2<br />
| 52 || 16 || 8 || 8 || 0 || 5x16bit<br>2x32bit<br />
| 0 || 2 || 2 || 1 || 2 || 0<br />
|-<br />
| 30F6012A || 7.85 || 30<br />
| 144 || 8 || 4<br />
| 52 || 16 || 8 || 8 || 0 || 5x16bit<br>2x32bit<br />
| 0 || 2 || 2 || 1 || 2 || 1<br />
|- <br />
| 33FJ128GP206 || 4.62 || 40<br />
| 128 || 8 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 1 || 0 || 1<br />
|-<br />
| 33FJ128GP306 || 4.81 || 40<br />
| 128 || 16 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 2 || 0 || 1<br />
|-<br />
| 33FJ128GP706 || 5.49 || 40<br />
| 128 || 16 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 2 || 2 || 1<br />
|-<br />
| 33FJ128MC506 || 4.97 || 40<br />
| 128 || 8 || 0<br />
| 53 || 16 || 8 || 8 || 8 || 9x16bit<br>4x32bit<br />
| 1 || 2 || 2 || 2 || 1 || 0<br />
|-<br />
| 33FJ128MC706 || 5.38 || 40<br />
| 128 || 16 || 0<br />
| 53 || 16 || 8 || 8 || 8 || 9x16bit<br>4x32bit<br />
| 1 || 2 || 2 || 2 || 1 || 0<br />
|-<br />
| 33FJ256GP506 || 6.11 || 40<br />
| 256 || 16 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 2 || 1 || 1<br />
|-<br />
|}<br />
<br />
===Web Page===<br />
*[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2529&param=en024856 Microchip Official Website]<br />
<br />
===Forum===<br />
*[http://direct.forum.microchip.com/default.aspx Microchip]: Official forum by Microchip<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=49 MPLAB ICD 2]: Subforum on ICD 2 programmer<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=57 MPLAB IDE]: Subforum on IDE<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=101 MPLAB C30 Compiler, ASM30, Link30 forum]: Subforum on C compiler. Refer to [http://ww1.microchip.com/downloads/en/DeviceDoc/C30_Users_Guide_51284e.pdf MPLAB C30 C Compiler User's Guide] Chapter 3<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=153 dsPIC30F Topics]: Subformum on dsPIC30F<br />
*[http://www.gnupic.org/ GNUPIC]: Discussion on PIC in Linux Systems<br />
**[http://www.linuxhacker.org/cgi-bin/ezmlm-cgi?1:dds:5443#b Debian]<br />
*[http://www.htsoft.com/forum/all/ubbthreads.php/Cat/0/C/6 HI-TECH Software Forum]: Discussion on dsPICC, a C compiler developed by HI-TECH<br />
*[http://piclist.com/techref/piclist/index.htm PICList]: Discussion on older PIC systems (not dsPIC)<br />
*[http://groups.google.com/group/pickit-devel PicKit]: Discussion on PICkit/PICkit 2 programmers<br />
*[http://sourceforge.net/forum/forum.php?forum_id=382005 FreeRTOS Real Time Kernel]: Open Discussion and Support on FreeRTOS <br />
<br />
===References===<br />
*dsPIC30F<br />
**[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2574 dsPIC30F Family Reference Manual Sections]: Contains detailed descriptions on dsPIC30F register definitions and example codes<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80169E.pdf dsPIC30F Family Reference Manual Errata (Use with revision 70046B only)]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70116F.pdf dsPIC30F5011, dsPIC30F5013 Data Sheet]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80210e.pdf dsPIC30F5011/5013 Rev. A1/A2 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80223D.pdf dsPIC30F5011/5013 Rev. A3 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70102G.pdf Flash Programming Specification]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70157B.pdf dsPIC30F Programmer's Reference Manual]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80170a.pdf dsPIC30F Programmer's Reference Manual Errata (use with revision DS70030E only)]<br />
<br />
*dsPIC33F<br />
**[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2573 dsPIC33F Family Reference Manual Sections]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70165E.pdf dsPIC33F Family Data Sheet]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80279B.pdf dsPIC33F Rev. A2 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80306A.pdf dsPIC33FJXXXGPX06/X08/X10 Rev. A2 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70152C.pdf Flash Programming Specification]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70172A.pdf dsPIC30F to dsPIC33F Conversion Guidelines]<br />
*ICD2 Programmer<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/51331B.pdf ICD2 User's Guide] <br />
*MPLAB<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/51519B.pdf MPLAB IDE User's Guide]<br />
*C30 Compiler<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/C30_Users_Guide_51284e.pdf MPLAB C30 C Compiler User's Guide]: Contains commands for using pic30-elf-gcc <br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/16bit_Language_Tool_Libraries_51456c.pdf 16-bit Language Tools Libraries]: Contains summaries and examples of using DSP libraries, standard C libraries and device libraries<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/Asm30_Link_Util_51317e.pdf MPLAB ASM30, MPLAB LINK30 and Utilities User's Guide]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/51322d.pdf dsPIC30F Language Tools Quick Reference Card]<br />
<br />
===Code Examples===<br />
*[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1408 Microchip Example Codes for dsPic]<br />
<br />
<br />
==Programming Methods==<br />
*There are 2 programming methods: In-Circuit Serial Programming (ICSP) and Run-Time Self-Programming (RTSP)<br />
*ICSP allows the devices to be programmed after being placed in a circuit board.<br />
*RTSP allows the devices to be programmed when an embedded program is already in operation.<br />
<br />
===ICSP: External Programmer (ICD2)===<br />
*Two types of ICSP are available: '''ICSP''' and '''Enhanced ICSP'''. Both of them require setting MCLR# to V<sub>IHH</sub> (9V – 13.25V).<br />
*Standard ICSP<br />
**Use external programmer (e.g. MPLAB<sup>®</sup> ICD 2, MPLAB<sup>®</sup> PM3 or PRO MATE<sup>®</sup> II) only.<br />
**Required low-level programming to erase, program and verify the chip.<br />
**Slower, because codes are serially executed.<br />
**Program memory can be erased using ''Normal-Voltage'' (4.5 – 5.5V) or ''Low-Voltage'' (2.5V – 4.5V).<br />
<br />
*Enhanced ICSP<br />
**Use external programmer and '''Programming Executive''' (PE).<br />
**PE is stored in the on-chip memory.<br />
**PE allows faster programming.<br />
**PE can be downloaded to the chip by external programmer using the standard ICSP method.<br />
**PE contains a small command set to erase, program and verify the chip, avoiding the need of low-level programming.<br />
<br />
====Hardware Interface====<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.1 Pin Used by ICSP<br />
! Pin Label !! Function !! Pin Number<br />
|- <br />
| MCLR# || Programming Enable|| 7<br />
|-<br />
| V<sub>DD</sub> || Power Supply || 10, 26, 38, 57<br />
|-<br />
| V<sub>SS</sub> || Ground || 9, 25, 41, 56<br />
|- <br />
| PGC || Serial Clock || 17<br />
|-<br />
| PGD || Serial Data || 18<br />
|-<br />
|}<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.2 Available Programmers in the Market<br />
! Product Name<br />
! Interface with PC<br />
! Interface with Device<br />
! Price (US)<br />
! Postage (US)<br />
! Total (US)<br />
|- <br />
| [http://direct.www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en010046&part=DV164005 MPLAB<sup>®</sup> ICD 2]<br />
| USB or RS232<br />
| [http://www.microchip.com/Microchip.WWW.SecureSoftwareList/secsoftwaredownload.aspx?device=en010046&lang=en&ReturnURL=http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en010046&part=DV164005# 6-PIN RJ-12 connector]<br />
| $159.99<br />
| -<br />
| -<br />
|-<br />
| [http://www.etekronics.com/product_info.php?cPath=24&products_id=48 Full Speed USB Microchip ICD2<br> Debugger and Programmer]<br />
| USB<br />
| 6-PIN ICSP connector<br>6-PIN RJ-12 connector<br />
| $72.00<br />
| $12.00<br />
| $84.00<br />
|-<br />
| [http://www.etekronics.com/product_info.php?cPath=24&products_id=47 Mini Microchip Compatible ICD2<br> Debugger and Programmer]<br />
| RS232<br />
| 6-PIN ICSP connector<br>6-PIN RJ-12 connector<br />
| $45.00<br />
| $10.00<br />
| $55.00<br />
|-<br />
| [http://www.inexglobal.com/microcontroller.php ICDX30]<br />
| RS232<br />
| 6-pin RJ-11<br />
| $51.00<br />
| $47.46<br />
| $98.46<br />
|-<br />
| *[http://www.sure-electronics.net Clone Microchip ICD2] (Now Using)<br />
| USB<br />
| 6-pin flat cables<br />
| $30.00<br />
| $12.00<br />
| $42.00<br />
|-<br />
|}<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.3 DIY ICD 2 Programmer Circuit<br />
! Source !! Schematic !! PIC16F877A Bootloader<br />
|- <br />
| [http://membres.lycos.fr/silicium31/Electronique/PIC/FreeIcdEnglish.htm Patrick Touzet]<br />
| [http://membres.lycos.fr/silicium31/Electronique/PIC/ICD2%20V1.3.pdf Yes]<br />
| [http://membres.lycos.fr/silicium31/Electronique/PIC/ICD2_FW.zip HEX]<br />
|-<br />
| [http://www.nebadje.org/doku.php?id=neblab:icd2clone Nebadje]<br />
| [http://people.ee.ethz.ch/~jbiveron/nebadje/ICD2_DOC.pdf Yes]<br />
| [http://people.ee.ethz.ch/~jbiveron/nebadje/ICD2_FW.zip Zip]<br />
|-<br />
|}<br />
<br />
====Software Interface====<br />
*The program can be written and compiled in an Integrated Development Environment (IDE) using either Assembly or C. The complied codes are then loaded to the device through the external programmer.<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.4 Summary of IDE<br />
! Product Name !! Features !! OS !! Price (US$)<br />
|- <br />
| [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en019469&part=SW007002 MPLAB<sup>®</sup> IDE]<br />
| Assembler Only<br />
| Windows<br />
| Free<br />
|-<br />
| [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en010065&part=SW006012 MPLAB<sup>®</sup> C30]<br />
| Assembler and C-Compiler<br />
| Windows<br />
| $895.00 (Free student version<sup>1</sup>)<br />
|-<br />
| [http://linux.softpedia.com/get/Science-and-Engineering/Electronic-Design-Automation-EDA-/Piklab-8099.shtml Piklab 0.12.0]<br />
| Assembler and C-Compiler<br />
| Linux<br />
| Free<sup>2</sup><br />
|}<br />
# Full-featured for the first 60 days. After 60 days, some code optimization functions are disabled. The compiler will continue to function after 60 days, but code size may increase.<br />
# The current version supports external programmer ICD 2, but not yet tested.<br />
<br />
===RTSP: COM Port (Bootloader)===<br />
*RTSP works in normal voltage (MCLR# no need to raise to V<sub>IHH</sub>).<br />
*No literature has mentioned the incorporation of Programming Executive (PE). Presumably, since Enhanced ICSP needs to set MCLR# to V<sub>IHH</sub>, RTSP cannot use PE.<br />
*Refer to [http://www.opencircuits.com/DsPIC30F_5011_Development_Board#Bootloader_Development bootloader section].<br />
<br />
<br />
==IC Requirements==<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 3.1 IC Requirements<br />
! Part No. !! Description <br />
! Min Temp !! Max Temp !! Min Volt !! Max Volt !! Typ Cur !! Max Cur<br />
|-valign="top"<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/70116F.pdf dsPIC30F5011-30I/PT] || uP <br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 2.5V <sup>[1]</sup>|| 5.5V<br />
| 145mA || 217mA<br />
|-<br />
| [http://datasheets.maxim-ic.com/en/ds/MAX3222-MAX3241.pdf MAX3232ESE] || RS232 driver<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 3.0V || 5.5V<br />
| 0.3mA || 1.0mA<br />
|-<br />
| [http://www.national.com/ds.cgi/DS/DS3695.pdf DS3695N] || RS485 driver<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 4.75V || 5.25V<br />
| 42mA || 60mA<br />
|-<br />
| [http://focus.ti.com/lit/ds/symlink/dac6574.pdf DAC6574IDGS] || 10-bit Quad-DAC I<sup>2</sup>C<br />
| -40<sup>o</sup>C || 105<sup>o</sup>C<br />
| 2.7V || 5.5V<br />
| 0.6mA || 0.9mA<br />
|-<br />
| [http://www.semiconductors.philips.com/acrobat/datasheets/74HC_HCT14_3.pdf 74HC14D] || Quad-Schmitt Trigger<br />
| -40<sup>o</sup>C || 125<sup>o</sup>C<br />
| 2.0V || 6.0V<br />
| || 0.02mA<br />
|-<br />
| '''Overall''' || <br />
| '''-40<sup>o</sup>C''' || '''85<sup>o</sup>C'''<br />
| '''4.75V''' || '''5.25V'''<br />
| || '''<300mA <sup>[2]</sup>'''<br />
|-<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/70165E.pdf dsPIC33FJ128GP306-I/PT] || uP <br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 3.0V <sup>[1]</sup>|| 3.6V<br />
| 74mA || 250mA<br />
|-<br />
| [http://www.analog.com/UploadedFiles/Data_Sheets/ADM3485E.pdf ADM3485EARZ] || RS485 driver<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 3.0V || 3.6V<br />
| 1.1mA || 2.2mA<br />
|-<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/21203N.pdf 24LC256-I/SN] || 256kBits I2C EEPROM<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 2.5V || 5.5V<br />
| 400uA || 3mA<br />
|-<br />
| [http://www.national.com/ds.cgi/LM/LM3940.pdf LM3940IMP-3.3] || 5V-3.3V Regulator<br />
| -40<sup>o</sup>C || 125<sup>o</sup>C<br />
| 5.0V || 7.5V<br />
| 10mA || 250mA<br />
|-<br />
|}<br />
#Minimum voltage measured is 3.3V (with 2 LEDs blinking) running at 30MHz.<br />
#Measured current at 5V is 180mA (with 2 LEDs blinking only)<br />
<br />
<br />
==Development Environment==<br />
<br />
===Windows===<br />
<br />
[[Image:PIC_setup_win.JPG]]<br />
<br />
*C-Compiler, Assembler and Linker are under GNU license.<br />
**MPLAB C30 C Compiler (*.c -> *.s)<br />
**MPLAB ASM30 Assembler (*.s -> *.o)<br />
**MPLAB LINK30 Linker (*.o -> *.bin)<br />
<br />
*PA optimizer, simulator, runtime libraries, header files, include files, and linker scripts are not covered by GNU. Reference is [http://direct.forum.microchip.com/tm.aspx?m=107208 here].<br />
<br />
*Microchip has integrated ASM30, LINK30, assembly header files, linker scripts in MPLAB IDE, which is free for download.<br />
*MPLAB C30 costs US$895. A 60-day free student version is also available. After 60-days, the optimizer is automatically disabled, while other tools can still function properly. Refer to Table 2.4.<br />
<br />
*C-libraries contained in C30 includes (Refer to [http://ww1.microchip.com/downloads/en/DeviceDoc/16bit_Language_Tool_Libraries_51456c.pdf 16-Bit Language Tools Libraries] from Microchip).<br />
<br />
<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 4.1 C Libraries in MPLAB C30<br />
! Library !! Directory <br>(\\Microchip\MPLAB C30) !! Major functions<br />
|-valign="top"<br />
| DSP Library <br>(e.g. libdsp-coff.a)<br />
| \lib <br> \src\dsp <br> \support\h<br />
| Vector, Matrix, Filter, etc.<br />
|-valign="top"<br />
| 16-Bit Peripheral Libraries <br>(e.g. libp30F5011-coff.a)<br />
| \lib <br> \src\peripheral <br> \support\h<br />
| ADC12, IOPort, UART, I<sup>2</sup>C, etc.<br />
|-valign="top"<br />
| Standard C Libraries <br>(e.g. libc-coff.a, libm-coff.a, libpic-coff.a)<br />
| \lib <br> \src\libm <br> \include<br />
| stdio.h, time.h, float.h, math.h, <br />
|-valign="top"<br />
| MPLAB C30 Built-in Functions<br />
| none<br />
| _buildin_addab, _buildin_add, _buildinmpy, etc<br />
|-<br />
|}<br />
<br />
===Linux===<br />
<br />
[[Image:PIC_setup_linux.JPG]]<br />
<br />
*C Compiler, Assembler and Linker are under GNU license.<br />
**The code can be downloaded from Microchip at [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en023073 here].<br />
**Current MPLAB ASM30 Assembler: v2.04<br />
**Current MPLAB C30 Compiler: v2.04<br />
<br />
*[http://gcc.gnu.org/ml/gcc/2005-02/msg01144.html John Steele Scott] has made templates that can be readily used by Debian-based systems. <br />
*For v1.32, the necessary conversion to *.deb has been done already at [http://noel.feld.cvut.cz/dspic/ here].<br />
**Download '''pic30-1.32-debian.tar.bz2''' for Template v1.32.<br />
**Download '''pic30-binutils_1.32-1_i386.deb''' for the assember.<br />
**Download '''pic30-gcc_1.32-1_i386.deb''' for the compiler.<br />
*For v2.00<br />
**goto http://www.baycom.org/~tom/dspic/<br />
**download pic30-gcc-2.00-1.i386.rpm and pic30-binutils-2.00-1.i386.rpm<br />
**convert to deb files<br />
**install these two deb files<br />
*For v3.01, convert the Toolchain following instructions at [http://www.nabble.com/Debian-templates-for-dsPIC-build-toolchain-3.01-tf4308624.html here]<br />
**pre-install these packages: dpkg-dev, debhelper, bison, flex, sysutils, gcc-3.3, fakeroot<br />
**pack pic30-binutils into deb file<br />
**install pic30-binutils<br />
**pack pic30-gcc-3.01 into deb file<br />
**install pic30-gcc-3.01<br />
**pack pic30-support into deb file<br />
**install pic30-support<br />
*'''Important Note''': Only the compiler is free. The header files and library are owned by Microchip. <br />
**Thomas Sailer suggested to download the Student version of C30 compiler and then build the libraries without source code. A package template for Fedora system is available [http://www.baycom.org/~tom/dspic/ here].<br />
**Instructions for filling the upstream direction is available [http://forum.microchip.com/printable.aspx?m=139360 here].<br />
**Alteratively, [https://gna.org/projects/pic30-libc/ Stephan Walter] has started a project to develop C Runtime Library for dsPIC. <br />
***Current libraries in version 0.1.1 include: assert.h, cdefs.h, ctype.h, errno.h, inttypes.h, stdint.h, stdio.h, stdlib.h, string.h<br />
<br />
*Burning Program Codes to Target Board<br />
#Use 'dspicprg and dspicdmp' utilities developed by [http://homerreid.ath.cx/misc/dspicprg/ Homer Reid] to burn hex code (*.hex) to devices. See Reference [http://forum.microchip.com/tm.aspx?m=94243 here]. Through serial port only?<br />
#Use [http://piklab.sourceforge.net/ Piklab IDE]. Details on file format not known.<br />
#Use [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en019469&part=SW007002 MPLAB IDE] to burn hex code (*.hex) to devices.<br />
<br />
===Code Optimization===<br />
*Below is a comparsion between different optimization levels for the project including drivers for 2 projects.<br />
<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 4.2 Comparison between differnt optimization levels<br />
! Optimization !! Description !! Project 1<br>Code Size<br>(byte) !! Project 1<br>Data Usage<br>(byte) !! Project 2<br>Code Size<br>(byte) !! Project 2<br>Data Usage<br>(byte)<br />
|-valign="top"<br />
| O0 <br />
| No optimization<br>Fastest Compilation<br />
| 6222 (9%) || 178 (4%) || 26,037 (38%) || 710 (17%)<br />
|-valign="top"<br />
| O1 <br />
| Optimize<br> Tries to reduce code size and execution time.<br />
| 4473 (6%) || 178 (4%) || 22,290 (32%) || 710 (17%)<br />
|-valign="top"<br />
| O2 <br />
| Optimize even more<br> Performs nearly all supported optimizations <br>that do not involve a space-speed trade-off. <br>Increases both compilation time and the <br>performance of the generated code.<br />
| 4422 (6%) || 178 (4%) || 21,993 (32%) || 710 (17%)<br />
|-valign="top"<br />
| O3 <br />
| Optimize yet more. <br>O3 turns on all optimizations specified by O2 <br>and also turns on the inline-functions option.<br />
| 4485 (6%) || 178 (4%) || 22,176 (32%) || 710 (17%)<br />
|-valign="top"<br />
| Os <br />
| Optimize for size. <br>Os enables all O2 optimizations that do not <br>typically increase code size. It also performs <br>further optimizations designed to reduce code <br>size.<br />
| 4356 (6%) || 178 (4%) || 21,885 (32%) || 710 (17%)<br />
|-<br />
|}<br />
<br />
<br />
==Software Architecture==<br />
+--------+--------+--------+--------+--------+<br />
Application | Task 1 | Task 2 | Task 3 | Task 4 | Task 5 |<br />
+--------+--------+--------+--------+--------+<br />
| POSIX API |<br />
+-------------------+------------------------+<br />
OS | Coroutine | FreeRTOS Scheduler |<br />
+-------------------+------------------------+<br />
| Drivers |<br />
+------+-----+-----+--------+-------+--------+<br />
Hardware | UART | ADC | DAC | EEPROM | PWM | TIMERS | <br />
+------+-----+-----+--------+-------+--------+<br />
*Currently, operating system is based on [http://www.freertos.org/ FreeRTOS] incorporating coroutine developed by [http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html Simon Tatham]<br />
*Software Drivers are to be developed to allow users at Application Level to use the hardware (e.g. ADC, DAC, UART, EEPROM etc) through the OS.<br />
*The interface between the drivers and the OS is based on [http://www.die.net/doc/linux/man/man2/ POSIX standard] (e.g. open(), write(), read(), ioctl(), usleep() etc).<br />
*The most up-to-date development can be found at repository [http://chungyan5.no-ip.org/vc/?root=freertos_posix freertos_posix]<br />
<br />
<br />
==Programming Tips==<br />
<br />
===Memory Map for 5011===<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 6.1 Memory Location<br />
! Type !! Start Address !! End Address !! Size<br />
|-valign="top"<br />
| Flash || 0x000000 ||0x00AFFF || 44K<sup>[1]</sup><br />
|-valign="top"<br />
| +--Flash: Reset Vector || 0x000000 ||0x000003 || 4<br />
|-valign="top"<br />
| +--Flash: Interrupt Vector Table || 0x000004 ||0x00007F || 124<br />
|-valign="top"<br />
| +--Flash: Alternate Vector Table || 0x000084 ||0x0000FF || 124<br />
|-valign="top"<br />
| +--Flash: User Program || 0x000100 ||0x00AFFF || 43.7K<br />
|-valign="top"<br />
| EEPROM || 0x7FFC00 || 0x7FFFFF || 1K<sup>[2]</sup><br />
|-valign="top"<br />
| Programming Executive || 0x800000 || 0x8005BF || 1472<br />
|-valign="top"<br />
| Unit ID || 0x8005C0 || 0x8005FF || 64<br />
|-valign="top"<br />
| Config Registers || 0xF80000 || 0xF8000F || 16<br />
|-valign="top"<br />
| Device ID || 0xFF0000 || 0xFF0003 || 4<br />
|-<br />
|}<br />
[1] Each address is 16-bit wide. Every two addresses correspond to a 24-bit instruction. Each even address contains 2 valid bytes; each odd address contains 1 valid byte plus 1 phathom byte.<br><br />
[2] Each address is 8-bit wide.<br />
<br />
===Data Location===<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 6.2 Data Location<br />
! Type !! Description !! Example<br />
|-valign="top"<br />
| _XBSS(N) <sup>[1]</sup><br />
| RAM Data in X-memory, aligned at N, no initilization<br />
| int _XBSS(32) xbuf[16];<br />
|-valign="top"<br />
| _XDATA(N) <sup>[1]</sup><br />
| RAM Data in X-memory, aligned at N, with initilization<br />
| int _XDATA(32) xbuf[] = {1, 2, 3, 4, 5};<br />
|-valign="top"<br />
| _YBSS(N) <sup>[1]</sup><br />
| RAM Data in Y-memory, aligned at N, no initilization<br />
| int _YBSS(32) ybuf[16];<br />
|-valign="top"<br />
| _YDATA(N) <sup>[1]</sup><br />
| RAM Data in Y-memory, aligned at N, with initilization<br />
| int _YDATA(32) ybuf[16] = {1, 2, 3, 4, 5};<br />
|-valign="top"<br />
| __attribute__((space(const)))<br />
| Flash ROM data, constant, accessed by normal C<br>statements, but 32K max.<br />
| int i __attribute__((space(const))) = 10;<br />
|-valign="top"<br />
| __attribute__((space(prog)))<br />
| Flash ROM data, read/write by program space visibility<br>window (psv)<br />
| int i __attribute__((space(prog)));<br />
|-valign="top"<br />
| __attribute__((space(auto_psv)))<br />
| Flash ROM data, read by normal C statements, write<br>by accessing psv<br />
| int i __attribute__((space(auto_psv)));<br />
|-valign="top"<br />
| __attribute__((space(psv)))<br />
| Flash ROM data, read/write by (psv)<br />
| int i __attribute__((space(psv)));<br />
|-valign="top"<br />
| _EEDATA(N) <sup>[1]</sup><br />
| ROM Data in EEPROM, aligned at N, read/write with psv<br />
| int _EEDATA(2) table[]={0, 1, 2, 3, 5, 8};<br />
|-valign="top"<br />
| _PERSISTENT<br />
| RAM Data, data remain after reset<br />
| int _PERSISTENT var1, var2;<br />
|-valign="top"<br />
| _NEAR<br />
| RAM Data at near section<br />
| int _NEAR var1, var2;<br />
|-valign="top"<br />
| _ISR<br />
| Interrupt service rountine<br />
| void _ISR _INT0Interrupt(void);<br />
|-valign="top"<br />
| _ISRFAST<br />
| Fast interrupt service rountine<br />
| void _ISRFAST _T0Interrupt(void);<br />
|-<br />
|}<br />
#N must be a power of two, with a minimum value of 2.<br />
<br />
===Configuration Bits===<br />
----<br />
*System clock source can be provided by:<br />
#Primary oscillator (OSC1, OSC2)<br />
#Secondary oscillator (SOSCO and SOSCI) with 32kHz crystal<br />
#Internal Fast RC (FRC) oscillator at 7.37MHz (7372800Hz)<br />
#Low-Power RC (LPRC) oscillator (Watchdog Timer) at 512 kHz.<br />
*These clock sources can be incorporated with interal Phase-locked-loop (PLL) x4, x8 or x16 to yield the osciallator frequrence F<sub>OSC</sub><br />
*The system clock is divided by 4 to yield the internal instruction cycle clock, F<sub>CY</sub>=F<sub>OSC</sub>/4<br />
*FRC with PLLx16 is used to achieve F<sub>CY</sub>=29.49MHz (29491200Hz or 30MIPS)<br />
<br />
//The code (MACRO) below is to be placed at the top of program (before main)<br />
_FOSC(CSW_FSCM_OFF & FRC_PLL16);<br />
_FWDT(WDT_OFF); //Turn off Watchdog Timer<br />
_FBORPOR(PBOR_ON & BORV_27 & MCLR_DIS & PWRT_16);<br />
_FGS(CODE_PROT_OFF); //Disable Code Protection<br />
<br />
===Timer===<br />
<br />
----<br />
*Each timer is 16-bit (i.e. counting from 0 to 65535).<br />
*Timer 2 and 3 can be incorporated together to form a 32-bit timer.<br />
*Prescale is the ratio between timer counts and system clock counts. Prescales of 1:1, 1:8, 1:64 and 1:256 are available.<br />
*Timers may be used to implement free time clock or mesaure time.<br />
<br />
====Free Time Clock====<br />
*Let required time for ticking be PERIOD.<br />
*Number of instruction cycles during PERIOD = PERIOD*F<sub>CY</sub> cycles<br />
*Using a prescale of 1:x, the timer period count register = # of cycles/x<br />
*e.g. PERIOD = 10ms; # of cycles = 10ms*30MHz = 300000 cylces; Using 1:64 Prescale, register setting = 300000/64 = 4688<br />
void time_init(void){<br />
TMR1 = 0; // Clear register<br />
PR1 = 4688; // Set period<br />
//============================================================<br />
_T1IF = 0; // Clear interrupt flag<br />
_T1IE = 1; // Enable interrupts<br />
//============================================================<br />
T1CONbits.TCS = 0; // Use internal clock source<br />
T1CONbits.TCKPS = 2; // Prescale Select 1:64<br />
T1CONbits.TON = 1; // Start the timer <br />
}<br />
//********************************************************************<br />
void _ISRFAST _T1Interrupt(void){<br />
_T1IF = 0; // Clear interrupt flag<br />
//Place user code here<br />
}<br />
<br />
====Time Measurement====<br />
*To measure the time taken for action(), use the code below:<br />
unsigned int measure_time(void){ <br />
PR3 = 0xFFFF; // Set counter to maximum<br />
_T3IF = 0; // Clear interrupt flag<br />
_T3IE = 0; // Disable interrupt<br />
T3CONbits.TON = 1; // Start the timer, TMR3 count up<br />
TMR3 = 0; //Clear TMR3 to start count up<br />
//====================================================<br />
//Add code here to wait for something to happen<br />
action();<br />
//====================================================<br />
T3CONbits.TON = 0; //Stop the timer<br />
//====================================================<br />
return (unsigned int) TMR3/FCY; //TMR/FCY yields the actual time<br />
}<br />
<br />
===Interrupt===<br />
<br />
----<br />
*Registers are involved in Interrupts includes: <br />
#Interrupt Flag Status (IFS0-IFS2) registers<br />
#Interrupt Enable Control (IEC0-IEC2) registers<br />
#Interrupt Priority Control (IPC0-IPC10) registers<br />
#Interrupt Priority Level (IPL) register<br />
#Global Interrupt Control (INTCON1, INTCON2) registers<br />
#Interrupt vector (INTTREG) register<br />
*User may assign priority level 0-7 to a specific interrupt using IPC. Setting priority to 0 disable a specific interrupt. Level 7 interrupt has the highest priority.<br />
*Current priority level is stored in bit<7:5> of Status Register (SR). Setting Interrupt Priority Level (IPL) to 7 disables all interrupts (except traps). <br />
*sti() and cli() can be defined to enable and disable global interrupts for time critical functions:<br />
#define IPL ( 0x00e0 )<br />
#define cli() SR |= IPL //Set IPL to 7<br />
#define sti() SR &= ~IPL //Set IPL to 0<br />
//============================================================<br />
char adc_ioctl(unsigned char request, unsigned char* argp){<br />
//...<br />
cli(); //Disable global interrupt<br />
for(;ch<=argp[0];ch++)<br />
adc_add_ch(argp[ch]); //Add adc channels<br />
sti(); //Enable global interrupt<br />
//...<br />
return 0;<br />
}<br />
*dsPic30F has an [http://ww1.microchip.com/downloads/en/DeviceDoc/80223D.pdf errate note] on the Interrupt Controller. When Nested Interrupt is turned on (NSTDIS=0 by default), a high priority interrupt negating a low priority interrupt may result in an Address Error.<br />
*To work around the problem, it is suggested by Microchip to use the following MACRO to protect:<br />
# the clearing of Interrput Flag<br />
# the disabling of Interrupt Enable<br />
# the lowering of Interrupt Priority <br />
# the modification of IPL in Status Register to 1-6<br />
#define DISI_PROTECT(X) { \<br />
__asm__ volatile ("DISI #0x1FFF");\<br />
X; \<br />
DISICNT = 0; \<br />
}<br />
*For example,<br />
void _ISR _T1Interrupt( void )<br />
{<br />
DISI_PROTECT(IFS0bits.T1IF = 0);<br />
//do something here...<br />
}<br />
<br />
===UART===<br />
<br />
----<br />
*5011 provides two UART channels UxART, for x=1, 2.<br />
*UxMODE, UxSTA, UxBRG are registers used to set the mode, indicate the status, and set the baud rate respectively.<br />
*For UART communications compatiable with RS232 standard, an external driver (e.g. MAX3232ESE) is needed.<br />
*For UART communications compatiable with RS485 standard, an external driver (e.g. DS3695N) is needed.<br />
====Auto baud rate detection====<br />
*The method is provided by [http://www.opencircuits.com/DsPIC30F_5011_Development_Board ingenia bootloader].<br />
*The PC sends a ASCII character 'U' (0x55) to the target board.<br />
*On the first rising edge of the start bit, the target board starts the timer.<br />
*At the fifth rising edge, the timer is stopped, let the count number be ''t_count''. <br />
**The measured period corresponds to 8 bits transmitted at a baud rate ''uxbrg''.<br />
_ _ _ _ _ _<br />
_|S|_|1|_|1|_|1|_|1|_|S|_ (S = Start Bit)<br />
<---------------><br />
Measured Time<br />
*The relationship between ''uxbrg'' and ''TMR'' is<br />
Measured Time (in seconds) = t_count/F<sub>cy</sub><br />
uxbrg = 1/(Measured Time/8)<br />
= 8*F<sub>cy</sub>/t_count<br />
*Since UxBRG is computed by:<br />
UxBRG = (F<sub>cy</sub>/(16*Baudrate)) -1<br />
= (F<sub>cy</sub>/(16*8*F<sub>cy</sub>/t_count)) -1<br />
= t_count/128 -1<br />
*The following is the code for auto baud rate detection for U2ART:<br />
unsigned int uart2_autobaud(void){<br />
U2MODEbits.ABAUD = 1; //Enable Autobaud detect from U2RX (from IC2 if 0)<br />
U2MODEbits.UARTEN = 1; //U2ART enable<br />
//Timer 3 Config==========================================================<br />
PR3 = 0xFFFF; // Set counter to maximum<br />
_T3IF = 0; // Clear interrupt flag<br />
_T3IE = 0; // Disable interrupt<br />
T3CONbits.TON = 1; // Start the timer, TMR3 count up<br />
//Input Capture Config====================================================<br />
IC2CONbits.ICM = 3; //Detect rising <br />
_IC2IF = 0; //Clear interrupt flag<br />
_IC2IE = 0; //Disable interrupt<br />
//Start Auto baud detection===============================================<br />
unsigned int i=0;<br />
cli(); //Disable Global Interrupt<br />
while(!_IC2IF); //1st rising edge detected<br />
TMR3 = 0; //Clear TMR3 to start count up<br />
_IC2IF = 0; //Clear interrupt flag<br />
while(!_IC2IF); //2nd rising edge detected<br />
_IC2IF = 0; //Clear interrupt flag<br />
while(!_IC2IF); //3rd rising edge detected<br />
_IC2IF = 0; //Clear interrupt flag<br />
while(!_IC2IF); //4th rising edge detected<br />
_IC2IF = 0; //Clear interrupt flag<br />
while(!_IC2IF); //5th rising edge detected<br />
_IC2IF = 0; //Clear interrupt flag<br />
T3CONbits.TON = 0; //Stop the timer<br />
sti(); //Enable Global Interrupt<br />
//Compute value for BRG register==========================================<br />
unsigned int time;<br />
time = ((TMR3+0x40)>>7)-1; //+0x40 for rounding<br />
//========================================================================<br />
return time;<br />
}<br />
*For 30MIP, tested speeds of transmission include 9600bps, 19200bps, 28800bps, 38400bps and 57600bps.<br />
====open()====<br />
*The following structures and variables are used as circular buffers for transmit and receive.<br />
struct UART_Rx{<br />
unsigned char wr;<br />
unsigned char rd;<br />
};<br />
struct UART_Tx{<br />
unsigned char wr; <br />
unsigned char rd;<br />
unsigned char tx_complete_flag;<br />
};<br />
struct UART_Rx uart_rx;<br />
struct UART_Tx uart_tx;<br />
unsigned char uart_rx_buf[MAX_UART_RX_BUF];<br />
unsigned char uart_tx_buf[MAX_UART_TX_BUF];<br />
<br />
char uart_open()<br />
{<br />
uart_rx.wr = 0;<br />
uart_rx.rd = 0;<br />
uart_tx.wr = 0;<br />
uart_tx.rd = 0;<br />
uart_tx.tx_complete_flag = 1;<br />
uart2_init();<br />
return 0;<br />
}<br />
<br />
void uart2_init(void){<br />
unsigned int u2brg = 97; <br />
#if(AUTO_BAUD_DECT>0)<br />
u2brg = uart2_autobaud();<br />
#endif<br />
U2BRG = u2brg; <br />
//=================================================================<br />
// Disable U2ART<br />
U2MODEbits.UARTEN = 0; //Disable U2ART module<br />
//=================================================================<br />
// Configure Interrupt Priority<br />
_U2RXIF = 0; //Clear Rx interrupt flags<br />
_U2TXIF = 0; //Clear Tx interrupt flags<br />
_U2RXIE = 1; //Receive interrupt: 0 disable, 1 enable <br />
_U2TXIE = 1; //Transmit interrupt: 0 disable, 1 enable<br />
//=================================================================<br />
// Configure Mode<br />
// +--Default: 8N1, no loopback, no wake in sleep mode, continue in idle mode<br />
// +--Diable autobaud detect<br />
// +--Enable U2ART module<br />
U2MODEbits.ABAUD = 0; //Disable Autobaud detect from U2RX <br />
U2MODEbits.UARTEN = 1; //U2ART enable<br />
//=================================================================<br />
// Configure Status<br />
// +--Default: TxInt when a char is transmitted, no break char<br />
// +--Default: RxInt when a char is received, no address detect, clear overflow<br />
// +--Enable Transmit<br />
U2STAbits.UTXEN = 1; //Tx enable<br />
}<br />
<br />
====write()====<br />
*This function writes a series of bytes to the circular buffer and start transmission.<br />
int uart_write(unsigned char *buf, int count)<br />
{<br />
//If transimt has not completed, return busy<br />
if(uart_tx.tx_complete_flag == 0){<br />
return -1; <br />
}<br />
else{<br />
uart_tx.tx_complete_flag = 0;<br />
}<br />
int next_data_pos;<br />
int byte = 0;<br />
for (; byte<count; byte++) {<br />
next_data_pos = pre_wr_cir254buf( (unsigned char)uart_tx.wr, <br />
(unsigned char)uart_tx.rd, <br />
MAX_UART_TX_BUF); <br />
if (next_data_pos!=255) {<br />
//Valid data is available<br />
uart_tx_buf[uart_tx.wr] = (unsigned char) buf[byte]; //copy the char to tx_buf<br />
uart_tx.wr = next_data_pos; //increment the ptr<br />
} else break;<br />
}<br />
//Raise Interrupt flag to initiate transmission<br />
_U2TXIF = 1; //Start interrupt<br />
return byte; <br />
}<br />
*The interrupt routine reads from the circular buffer and send the data. The uart is opened such that the module will generate an TX Interrupt when it a byte is sent.<br />
void _ISR _U2TXInterrupt(void){<br />
DISI_PROTECT(_U2TXIF = 0); //Clear Interrupt Flag<br />
unsigned char next_data_pos;<br />
next_data_pos = pre_rd_cir254buf( (unsigned char)uart_tx.wr,<br />
(unsigned char)uart_tx.rd, <br />
MAX_UART_TX_BUF);<br />
if (next_data_pos!= 255) {<br />
//Valid Data is available to transmit<br />
U2TXREG = (uart_tx_buf[(unsigned char)uart_tx.rd] & 0xFF); //send next byte...<br />
uart_tx.rd = (unsigned char) next_data_pos; //update rd pointer<br />
} else {<br />
//Transimission has completed<br />
uart_tx.tx_complete_flag = 1; // change to empty of tx<br />
}<br />
}<br />
<br />
====read()====<br />
*The interrupt routine writes to the circular buffer when space is available.<br />
void _ISR _U2RXInterrupt(void){<br />
unsigned char next_data_pos;<br />
if ( U2STAbits.URXDA ){<br />
next_data_pos = pre_wr_cir254buf( uart_rx.wr, uart_rx.rd, MAX_UART_RX_BUF);<br />
if (next_data_pos!=255) {<br />
//If buffer is not full<br />
uart_rx_buf[uart_rx.wr] = (unsigned char) U2RXREG; //Read the data from buffer<br />
uart_rx.wr = next_data_pos;<br />
} <br />
else{<br />
//When buffer is full, still remove data from register, butthe incoming data is lost<br />
next_data_pos = (unsigned char) U2RXREG; //Read the data from buffer<br />
} <br />
}<br />
DISI_PROTECT(_U2RXIF = 0); //Clear the flag<br />
}<br />
*This function reads one byte from the circular buffer.<br />
int uart_read(unsigned char *buf)<br />
{<br />
int next_data_pos;<br />
next_data_pos = pre_rd_cir254buf( uart_rx.wr, uart_rx.rd, MAX_UART_RX_BUF);<br />
//Copy 1 byte when data is available<br />
if (next_data_pos!=255) <br />
{<br />
*buf = uart_rx_buf[uart_rx.rd]; //copy the stored data to buf<br />
uart_rx.rd = next_data_pos; //update the ptr<br />
return 1;<br />
}<br />
//No data can be copied<br />
else<br />
{<br />
return 0;<br />
} <br />
}<br />
<br />
===I<sup>2</sup>C===<br />
<br />
----<br />
*Two lines are devoted for the serial communication. SCL for clock, SDA for data.<br />
*Standard communication speed includes<br />
#Standard speed mode: 100kHz<br />
#Fast speed mode: 400kHz<br />
#High speed mode: 3.4MHz<br />
*dsPIC30f5011 supports standard and fast speed modes. The maximum speed attainable is 1MHz.<br />
*Pull-up resistors are required for both SCL and SDA. Minimum pull-up resistance is given by:<br />
Pull-up resistor (min) = (V<sub>dd</sub>-0.4)/0.003 ...... [See section 21.8 in Family reference manual]<br />
*2.2Kohm is typical for standard speed mode.<br />
*After initiating a start/stop/restart bit, add a small delay (e.g. no operation) before polling the corresponding control bit (hardware controlled).<br />
*After sending a byte and receiving an acknowledgement from the slave device, ensure to change to idle state.<br />
<br />
====open()====<br />
*The following structure is used to record whether special bits are needed to be sent.<br />
typedef union{<br />
unsigned char val;<br />
struct{<br />
unsigned START:1; //start<br />
unsigned RESTART:1; //restart<br />
unsigned STOP:1; //stop<br />
unsigned NACK:1; //not acknowledgment<br />
unsigned :1;<br />
unsigned :1;<br />
unsigned :1;<br />
unsigned :1; <br />
}bits;<br />
} I2C_STATUS;<br />
static I2C_STATUS i2c_status; <br />
<br />
*Initializing I<sup>2</sup>C with default speed I2C_BRG without interrupts.<br />
void i2c_open(void)<br />
{<br />
//Open i2c if not already opened<br />
if(I2CCONbits.I2CEN == 0)<br />
{<br />
_SI2CIF = 0; //Clear Slave interrupt<br />
_MI2CIF = 0; //Clear Master interrupt<br />
_SI2CIE = 0; //Disable Slave interrupt<br />
_MI2CIE = 0; //Disable Master interrupt<br />
I2CBRG = I2C_BRG;<br />
I2CCONbits.I2CEN = 1; //Enable I2C module <br />
i2cIdle(); //I2C bus at idle state, awaiting transimission<br />
i2c_status.val = 0; //clear status flags<br />
}<br />
}<br />
<br />
====ioctl()====<br />
*Use this function before read/write to append special bits before or after the data byte.<br />
char i2c_ioctl(unsigned char request, unsigned char* argp)<br />
{<br />
switch(request){<br />
case I2C_SET_STATUS:<br />
i2c_status.val = *argp;<br />
break;<br />
default:<br />
return -1; //request code not recognised <br />
}<br />
return 0;<br />
}<br />
<br />
====write()====<br />
*This function sends an 8-bit data using the I2C protocol.<br />
Mst/Slv _______ M ____M___ S M ________ <br />
SDA (Data) |S| data |A|S|<br />
|T| |C|T|<br />
|A|XXXXXXXX|K|P|<br />
*Use ioctl() to select whether a start/restart/stop bit is required.<br />
*If slave does not respond after ACK_TIMEOUT, the transmission is considered unsucessful.<br />
int i2c_write(unsigned char *buf)<br />
{<br />
unsigned int count = 0;<br />
if(i2c_status.bits.START)<br />
{<br />
I2CCONbits.SEN = 1; <br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.SEN); //Wait till Start sequence is completed<br />
}<br />
else if(i2c_status.bits.RESTART)<br />
{<br />
I2CCONbits.RSEN = 1; <br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.RSEN); //Wait till Start sequence is completed<br />
}<br />
I2CTRN = *buf; //Transmit register<br />
while(I2CSTATbits.TBF); //Wait for transmit buffer to empty<br />
while(I2CSTATbits.ACKSTAT){<br />
if(++count > ACK_TIMEOUT){<br />
//Slave did not acknowledge, byte did not transmit sucessfully, <br />
//send stop bit to reset i2c<br />
I2CCONbits.PEN = 1;<br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.PEN); //Wait till stop sequence is completed<br />
i2cIdle();<br />
return 0;<br />
}<br />
}<br />
i2cIdle();<br />
if(i2c_status.bits.STOP)<br />
{<br />
I2CCONbits.PEN = 1;<br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.PEN); //Wait till stop sequence is completed<br />
i2cIdle();<br />
}<br />
i2c_status.val = 0; //Clear status<br />
return 1;<br />
}<br />
<br />
====read()====<br />
*This function reads 1 byte from slave using the I2C protocol.<br />
Mst/Slv ____ ___S____ M M _____ <br />
SDA (Data) | data |A|S|<br />
| |C|T|<br />
|XXXXXXXX|K|P|<br />
*Use ioctl() to select whether an ACK/NACK and/or STOP bit is needed to be sent.<br />
int i2c_read(unsigned char *buf)<br />
{<br />
I2CCONbits.RCEN = 1; //Enable Receive<br />
while(I2CCONbits.RCEN);<br />
I2CSTATbits.I2COV = 0; //Clear receive overflow<br />
*buf = (unsigned char) I2CRCV; //Access the receive buffer<br />
I2CCONbits.ACKDT = (i2c_status.bits.NACK)? 1 : 0;<br />
I2CCONbits.ACKEN = 1; //Send Acknowledgement/Not Acknowledgement<br />
i2cIdle(); //I2C bus at idle state, awaiting transimission<br />
if(i2c_status.bits.STOP)<br />
{<br />
I2CCONbits.PEN = 1;<br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.PEN); //Wait till stop sequence is completed<br />
i2cIdle();<br />
}<br />
i2c_status.val = 0; //Clear status<br />
return 1;<br />
}<br />
<br />
====Example====<br />
Mst/Slv _______ M ___M___ M S ____M___ S M ___M___ M S ___S____ M ___S____ M M _____ <br />
SDA (Data) |S| | |A| |A|R| | |A| |A| |N|S|<br />
|T|address|W|C|channelA|C|E|address|R|C| Data H |C| Data L |A|T|<br />
|A|1001111|0|K|00010010|K|S|1001111|1|K|10101010|K|10XXXXXX|K|P|<br />
<br />
/*<br />
* Send start bit, slave address (Write Mode)<br />
*/ <br />
status = I2C_START;<br />
i2c_ioctl(I2C_SET_STATUS, &status);<br />
data = (unsigned char) I2C_SLAVE_ADDR;<br />
i2c_write(&data);<br />
/*<br />
* Send control byte: Channel select<br />
*/<br />
data = (unsigned char) ctrl_byte;<br />
i2c_write(&data);<br />
/*<br />
* Send restart bit, slave address (Read Mode)<br />
*/<br />
status = I2C_RESTART;<br />
i2c_ioctl(I2C_SET_STATUS, &status);<br />
data = (unsigned char) (I2C_SLAVE_ADDR|0x01);<br />
i2c_write(&data);<br />
/*<br />
* Receive High Byte with Acknowledgment<br />
*/<br />
i2c_read(&data);<br />
usr_data.high = (unsigned char) data;<br />
/*<br />
* Receive Low Byte with Not Acknowledgment and stop bit<br />
*/ <br />
status = I2C_NACK | I2C_STOP;<br />
i2c_ioctl(I2C_SET_STATUS, &status);<br />
i2c_read(&data);<br />
usr_data.low = (unsigned char) data;<br />
<br />
===ADC===<br />
<br />
----<br />
*12-bit ADC: (Max 16 Channels)<br />
*Allow a maximum of 2 sets of analog input multiplexer configurations, MUX A and MUX B (Normally use one only).<br />
*A maximum of 200kps of sampling rate when using auto sampling mode.<br />
====open()====<br />
*The following variables are required.<br />
unsigned int adc_buf[ADC_MAX_CH]; //Store most updated data<br />
volatile unsigned int* ADC16Ptr = &ADCBUF0; //Pointer to ADC register buffer, <br />
unsigned char adc_ch_select = 0; //Pointer to channel to be read from<br />
unsigned char adc_data_ready = 0; //Indicate if RAM data is ready for output<br />
*Configuration is highlighted below.<br />
**Interrupt: The ADC module will be set to interrupt when the specified channels are updated.<br />
**I/O: Set the corresponding TRISBX bits (digit i/o config) to input (i.e. = 1), and set corresponding bits in ADPCFG (analog config) to zero.<br />
**Scanning Mode: Scan mode is used. In this mode, the Sample and Hold (S/H) is switched between the channels specified by ADCSSL (Scan select register).<br />
**Reference Voltage for S/H: Only MUX A is used. By default, the negative reference voltage of the S/H is connected to V<sub>REF-</sub>.<br />
**Settings for ADC Operation: For 200kbps operation, the voltage references for the ADC voltage are connected to V<sub>REF+</sub> and V<sub>REF-</sub>. Scan input is enabled, and the module will generate an interrupt when all selected channels have been scanned.<br />
**Sampling Rate: T<sub>AD</sub> refers to the time unit for the ADC clock. To configure the ADC module at 200kbps, the minimum sampling time of 1T<sub>AD</sub> = 334ns is required. ADCS<5:0> in ADCON3 register is used to set the time, which is given by:<br />
ADCS<5:0> = 2(T<sub>AD</sub>/T<sub>CY</sub>)-1 <br />
= 2(334e-9/33.34e-9)-1 <br />
= 19<br />
<br />
char adc_open(int flags)<br />
{<br />
// Configure interrupt<br />
_ADIF = 0; //clear ADC interrupt flag<br />
_ADIE = 1; //enable adc interrupt<br />
// Configure analog i/o <br />
_TRISB0 = 1;<br />
_TRISB1 = 1; <br />
ADPCFG = 0xFFFC; //Enable AN0 (Vref+) and AN1 (Vref-)<br />
// Configure scan input channels <br />
ADCSSL = 0x0003; //0 => Skip, 1 => Scan<br />
// Configure CH0 Sample and Hold for 200kbps<br />
// +-- Use MUX A only<br />
// +-- Set CH0 S/H -ve to VRef-<br />
ADCHSbits.CH0NA = 0;<br />
// ADCCON3:<br />
// +--Auto Sample Time = 1TAD<br />
// +--A/D Conversion Clock Source = system clock<br />
// +--A/D Conversion Clock Select ADCS<5:0>= 2(TAD/TCY)-1<br />
// 200kbps(Sampling frequency)<br />
ADCON3bits.SAMC = ADC_ACQ_TIME; //1TAD for sampling time<br />
ADCON3bits.ADRC = 0; //Use system clock<br />
ADCON3bits.ADCS = ADC_ADCS; //each conversion requires 14TAD<br />
// ADCCON2:<br />
// +--Default: Use MUX A, No splitting of Buffer<br />
// +--Voltage Reference Configuration Vref+ and Vref-<br />
// +--Scan Input Selections<br />
// +--5 samples between interrupt<br />
ADCON2bits.VCFG = 3; //External Vref+, Vref-<br />
ADCON2bits.CSCNA = 1; //Scan input<br />
ADCON2bits.SMPI = 1; //take 2 samples (one sample per channel) per interrupt<br />
// ADCCON1:<br />
// +--Default: continue in idle mode, integer format<br />
// +--Enable ADC, Conversion Trigger Source Auto, Auto sampling on<br />
ADCON1bits.FORM = 0; //[0:integer]; [2 fractional]; [3 siged fractional]<br />
ADCON1bits.SSRC = 7; //auto covert, using internal clock source<br />
ADCON1bits.ASAM = 1; //auto setting of SAMP bit<br />
ADCON1bits.ADON = 1; //Turn on module<br />
return 0;<br />
}<br />
<br />
====read()====<br />
*16 registers (ADCBUF0 -ADCBUF15) are dedicated to store the ADC data between interrupts. However, the data in ADCBUFx does not necessarily correspond to the data taken for channel x. Since the lowest register will always be filled first, when some of the channels are not scanned (i.e. skipped), care must be taken. The following code checks the ADCSSL register for the current scanning channels and moves the data to the corresponding position in *adc_buf.<br />
void _ISR _ADCInterrupt(void){<br />
unsigned int channel = 0;<br />
unsigned int buffer = 0;<br />
for (; channel<ADC_MAX_CH; channel++)<br />
{<br />
if(select(channel)) //Check if channel has been selected<br />
{<br />
adc_buf[channel] = ADC16Ptr[buffer]; //Copy data to adc_buf<br />
buffer++;<br />
}<br />
}<br />
adc_data_ready = 1;<br />
DISI_PROTECT(_ADIF = 0); //Clear adc interrupt<br />
}<br />
<br />
static unsigned char select(unsigned char ch)<br />
{<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
if(ADCSSL & mask)<br />
return 1;<br />
return 0;<br />
}<br />
*User can read from the buffer at anytime to get the most updated analog values.<br />
int adc_read(unsigned int* buf, int count)<br />
{<br />
if(adc_data_ready == 1)<br />
{<br />
int num_channel = count/2; //number of channels to read<br />
unsigned char channel = adc_ch_select; //index for adc_buf<br />
int i = 0; //index for buf<br />
while(i<num_channel && channel<ADC_MAX_CH)<br />
{ <br />
//Loop only for specified number of channel or all channels <br />
buf[i++] = adc_buf[channel++]; //use data in local buffer<br />
while(select(channel)==0)<br />
{ //increment to next valid channel<br />
channel++; <br />
if(channel >= ADC_MAX_CH) break;<br />
}<br />
}<br />
return 2*i;<br />
}<br />
return -1;<br />
}<br />
<br />
====ioctl()====<br />
*This function is used to add or remove channels from the ADC scanning process.<br />
char adc_ioctl(unsigned char request, unsigned char* argp)<br />
{<br />
switch(request)<br />
{<br />
case ADC_ADD_CH:<br />
//ADD channels to current set==========================<br />
cli(); //Disable global interrupt<br />
if(select(argp[0]) == 0){ //If channel not in scan list<br />
adcAdd(argp[0]); //Add individual channel to scan list<br />
adc_data_ready = 0; //First data not ready yet, until interrupt occurs<br />
}<br />
adc_ch_select = argp[0]; //Select current channel for reading<br />
sti(); //Enable global interrupt<br />
break;<br />
case ADC_RM_CH:<br />
//REMOVE channels from current set==========================<br />
cli(); //Disable global interrupt<br />
if(select(argp[0])){ //If channel in scan list <br />
adcRm(argp[0]); //Remove individual channel<br />
adc_ch_select = 0; //Reset to AN0<br />
}<br />
sti(); //Enable global interrupt<br />
break;<br />
default:<br />
return -1; //request code not recognised <br />
}<br />
return 0;<br />
}<br />
*Channels may be added or removed by changing _TRISBX, ADPCFG, ADCSSL and ADCON2bits.SMPI.<br />
void adc_add_ch(unsigned char ch){<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
TRISB = TRISB | mask;<br />
ADCSSL = ADCSSL | mask; <br />
ADPCFG = ~ADCSSL;<br />
ADCON2bits.SMPI++; //take one more sample per interrupt<br />
}<br />
<br />
void adc_rm_ch(unsigned char ch){<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
ADPCFG = ADPCFG | mask;<br />
ADCSSL = ~ADPCFG;<br />
ADCON2bits.SMPI--; //take one less sample per interrupt<br />
}<br />
<br />
===EEPROM===<br />
<br />
----<br />
*5011 has 1024 bytes of EEPROM, readable and writable under normal voltage (5V).<br />
*To use, declare:<br />
unsigned char _EEDATA(2) eeData[1024]={ 0x00, 0x00, 0x00, 0x00, .... }<br />
unsigned int byte_pointer = 0;<br />
====lseek()====<br />
*This function moves the pointer to the desired position before a reading/writing operation is performed.<br />
int eeprom_lseek(int offset, unsigned char whence){<br />
byte_pointer = offset;<br />
return byte_pointer;<br />
}<br />
====read()====<br />
*This function read ''count'' bytes from the eeprom.<br />
int eeprom_read(unsigned char* buf, int count){<br />
int i=0;<br />
for(; i<count && byte_pointer < 1024; i++){<br />
readEEByte( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + byte_pointer, <br />
&buf[i]);<br />
byte_pointer++; //Update global pointer<br />
}<br />
return i; //read i bytes successful <br />
}<br />
*readEEByte() is implemented in assembly code as follows:<br />
.global _readEEByte<br />
_readEEByte:<br />
push TBLPAG ;w0 = base of eeData<br />
mov w0, TBLPAG ;w1 = offset for eeData in byte<br />
tblrdl.b [w1], [w2] ;w2 = pointer to user buffer<br />
pop TBLPAG<br />
return<br />
<br />
====write()====<br />
*This function write ''count'' bytes to eeprom.<br />
int eeprom_write(unsigned char* buf, int count){<br />
char isOddAddr = byte_pointer%2; //current address is odd<br />
char isOddByte = count%2; //number of bytes to write is odd<br />
//=================================================================<br />
unsigned int word_offset = byte_pointer>>1; //div by 2 and round down<br />
int max_write;<br />
max_write = (isOddAddr == 0 && isOddByte == 0) ? (count>>1) : (count>>1)+1;<br />
//=================================================================<br />
unsigned int word_data; //Store word to be written<br />
int byte_wr = 0; //number of bytes written, i.e buffer pointer<br />
int i = 0;<br />
//=================================================================<br />
for(; i<max_write && word_offset<512; i++, word_offset++){<br />
if(i==0 && isOddAddr){<br />
//First byte not used<br />
//============================================save first byte<br />
readEEByte( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + byte_pointer - 1,<br />
&word_data);<br />
//===========================================================<br />
word_data = ((unsigned int)buf[0] << 8) + (0xFF & word_data);<br />
byte_wr++; //Update buffer pointer<br />
byte_pointer++; //Update global pointer<br />
} else if(i==max_write-1 && ((isOddAddr && sOddByte==0)||(isOddAddr==0 && isOddByte))){<br />
//Last byte not used<br />
//=============================================save last byte<br />
readEEByte( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + byte_pointer + 1,<br />
&word_data);<br />
//============================================================<br />
word_data = (word_data << 8) + buf[byte_wr];<br />
byte_wr++; //Update buffer pointer<br />
byte_pointer++; //Update global pointer<br />
} else{<br />
//Both bytes valid<br />
word_data = ((unsigned int)buf[byte_wr+1] << 8) + buf[byte_wr];<br />
byte_wr+=2; //Update buffer pointer<br />
byte_pointer+=2; //Update global pointer<br />
}<br />
//==================================================================<br />
eraseEEWord( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + 2*word_offset);<br />
writeEEWord( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + 2*word_offset,<br />
&word_data);<br />
//==================================================================<br />
}<br />
return byte_wr; //No. of byte written<br />
}<br />
*eraseEEWord and writeEEWord are implemented in assembly.<br />
.global _eraseEEWord<br />
_eraseEEWord:<br />
push TBLPAG <br />
mov w0, NVMADRU ;w0 = base of eeData<br />
mov w1, NVMADR ;w1 = offset for eeData in word<br />
mov #0x4044, w0 <br />
mov w0, NVMCON ;Set to erase operation<br />
push SR ;Disable global interrupts<br />
mov #0x00E0, w0<br />
ior SR<br />
mov #0x55, w0 ;Write the KEY sequence<br />
mov w0, NVMKEY<br />
mov #0xAA, w0 <br />
mov w0, NVMKEY<br />
bset NVMCON, #15 ;Start the erase cycle, bit 15 = WR<br />
nop<br />
nop<br />
L1: btsc NVMCON, #15 ;while(NVMCONbits.WR)<br />
bra L1<br />
clr w0<br />
pop SR ;Enable global interrupts<br />
pop TBLPAG<br />
return<br />
<br />
.global _writeEEWord<br />
_writeEEWord:<br />
push TBLPAG ;w0 = base of eeData<br />
mov w0, TBLPAG ;w1 = offset for eeData in byte<br />
tblwtl [w2], [w1] ;w2 = pointer to user buffer<br />
mov #0x4004, w0 ;Set to write operation<br />
MOV w0, NVMCON<br />
push SR ;Disable global interrupts<br />
mov #0x00E0, w0<br />
ior SR<br />
mov #0x55, w0 ;Write the KEY sequence<br />
mov w0, NVMKEY<br />
mov #0xAA, w0 <br />
mov w0, NVMKEY<br />
bset NVMCON, #15 ;Start the erase cycle, bit 15 = WR<br />
nop<br />
nop<br />
L2: btsc NVMCON, #15 ;while(NVMCONbits.WR)<br />
bra L2<br />
clr w0<br />
pop SR ;Enable global interrupts<br />
pop TBLPAG<br />
return<br />
<br />
===Simple PWM (Output Compare Module)===<br />
<br />
----<br />
<br />
*The PWM module consists of 8 channels using the output compare module of dsPic.<br />
*These channels are locate at pin 46 (OC1), 49 (OC2), 50 (OC3), 51 (OC4), 52 (OC5), 53 (OC6), 54 (OC7), 55 (OC8). These pins are shared with port D.<br />
*The range of PWM freqeuencies obtainable is 2Hz to 15MHz (See Figure 6.3). Suggested range of operation is 2Hz to 120kHz. The relationship between resolution ''r'' and PWM frequency ''f''<sub>PWM</sub> is given by:<br />
f<sub>PWM</sub> = f<sub>CY</sub>/(Prescale*10<sup>rlog(2)</sup>)<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 6.3 Relationship of Resolution and PWM Frequency<br />
! Resolution (bit) !! Prescale=1 !! Prescale=8 !! Prescale=64 !! Prescale=256<br />
|- <br />
|1||15,000,000 ||1,875,000 ||234,375||58,594 <br />
|- <br />
|2||7,500,000 ||937,500 ||117,188 ||29,297 <br />
|- <br />
|3||3,750,000 ||468,750 ||58,594 ||14,648 <br />
|- <br />
|4||1,875,000 ||234,375 ||29,297 ||7,324 <br />
|- <br />
|5||937,500 ||117,188 ||14,648 ||3,662 <br />
|- <br />
|6||468,750 ||58,594 ||7,324 ||1,831 <br />
|- <br />
|7||234,375 ||29,297 ||3,662 ||916 <br />
|- <br />
|8||117,188 ||14,648 ||1,831||458 <br />
|- <br />
|9||58,594 ||7,324 ||916 ||229 <br />
|- <br />
|10||29,297 ||3,662 ||458 ||114 <br />
|- <br />
|11||14,648 ||1,831 ||229||57 <br />
|- <br />
|12||7,324 ||916 ||114 ||29 <br />
|- <br />
|13||3,662 ||458 ||57 ||14 <br />
|- <br />
|14||1,831 ||229 ||29 ||7 <br />
|- <br />
|15||916 ||114 ||14 ||4 <br />
|- <br />
|16||458 ||57 ||7 ||2 <br />
|-<br />
|}<br />
<br />
====open()====<br />
*A timer (either Timer 2 or 3) is needed to determine the pwm period. The following code uses timer 2 for all 8 channels.<br />
void pwm_open(void){<br />
OC1CON = 0; OC2CON = 0; //Disable all output compare modules<br />
OC3CON = 0; OC4CON = 0;<br />
OC5CON = 0; OC6CON = 0;<br />
OC7CON = 0; OC8CON = 0;<br />
//============================================================<br />
TMR2 = 0; // Clear register<br />
PR2 = 0xFFFF; // Set to Maximum<br />
//============================================================<br />
_T2IF = 0; // Clear interrupt flag<br />
_T2IE = 0 // Enable interrupts<br />
//============================================================<br />
T2CONbits.TCS = 0; // Use internal clock source<br />
T2CONbits.TCKPS = 0; // Prescale Select 1:1<br />
//============================================================<br />
T2CONbits.TON = 1; // Start the timer <br />
}<br />
<br />
====ioctl()====<br />
*User should select the channel and set the pwm period using the functions below before issuing the duty cycle:<br />
char pwm_ioctl(unsigned char request, unsigned long* argp){<br />
unsigned int value;<br />
unsigned char mask;<br />
switch(request){<br />
case PWM_SET_PERIOD:<br />
return setPeriodNPrescale(argp[0]);<br />
case PWM_SELECT_CH:<br />
pwm_channel = argp[0];<br />
mask = 0x01 << pwm_channel;<br />
pwm_status = pwm_status | mask;<br />
return 0;<br />
default:<br />
return -1;<br />
}<br />
}<br />
char setPeriodNPrescale(unsigned long value_ns){<br />
unsigned long ans;<br />
unsigned long long numerator = (unsigned long long)value_ns*SYSTEM_FREQ_MHZ;<br />
int index= -1;<br />
unsigned long denominator;<br />
//-------------------------------------------------<br />
do{<br />
denominator = (unsigned long)1000*pwm_prescale[++index];<br />
ans = (unsigned long)(((long double)numerator/denominator) + 0.5) - 1; //round to nearest int<br />
} while(ans > 0x0000FFFF && index < 3);<br />
//-------------------------------------------------<br />
if(ans > 0x0000FFFF)<br />
return -1;<br />
//-------------------------------------------------<br />
T2CONbits.TON = 0; // Turn off the timer<br />
T2CONbits.TCKPS = index; // Change prescale factor<br />
PR2 = (unsigned int) ans; // Set to Maximum<br />
T2CONbits.TON = 1; // Turn on the timer <br />
//-------------------------------------------------<br />
return 0;<br />
}<br />
<br />
====write()====<br />
*User can change the duty cycle using the following functions<br />
int pwm_write(unsigned long* buf){<br />
if((pwm_status & (0x01 << pwm_channel)) == 0){<br />
return -1; //Channel has not been enabled<br />
}<br />
switch(pwm_channel){<br />
case 0:<br />
OC1RS = calcDCycle(buf[0]); OC1R = OC1RS; <br />
OC1CONbits.OCM = 6; //Simple PWM, Fault pin disabled<br />
break;<br />
case 1:<br />
OC2RS = calcDCycle(buf[0]); OC2R = OC2RS; <br />
OC2CONbits.OCM = 6; //Simple PWM, Fault pin disabled<br />
break;<br />
...<br />
case 7:<br />
OC8RS = calcDCycle(buf[0]); OC8R = OC8RS; <br />
OC8CONbits.OCM = 6; //Simple PWM, Fault pin disabled<br />
break; <br />
default:<br />
return -1;<br />
}<br />
return 4;<br />
}<br />
unsigned int calcDCycle(unsigned long value_ns){<br />
unsigned long long numerator = (unsigned long long)value_ns*SYSTEM_FREQ_MHZ;<br />
unsigned int index = T2CONbits.TCKPS;<br />
unsigned long denominator = (unsigned long)1000*pwm_prescale[index];<br />
return (unsigned int)(((long double)numerator/denominator) + 0.5) - 1; //round to nearest int<br />
}<br />
<br />
====Propagration Delay====<br />
*PWM channels sharing the same timer will have their PWM signals synchronised (i.e. the HIGH state of the duty cycle are all triggered together).<br />
*To introduced delay to the PWM signals, the signal from selected channels may be made to pass through a series of inverters (e.g. 74HC14D). This adds propagation delay to the signal.<br />
*However, as propagration delay of logic gates depends on applied voltage, temperature and load capacitance, the accuracy is low and performance is poor. For accurate delay, delay lines may be used, but they are expensive.<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 6.4 Propagation Delay of [http://www.nxp.com/acrobat_download/datasheets/74HC_HCT14_3.pdf Philips 74HC14D]<sup>[1], [2]</sup><br />
! !! 3.3V !! !! !! 5.0V !! !!<br />
|- <br />
! Number of Gates !! A !! B !! C !! A !! B !! C<br />
|- <br />
| 2 <br />
| 21ns (10.5)|| 23ns (11.5)|| 22ns (11.0)<br />
| 15ns (7.5)|| 14ns (7.0)|| 14ns (7.0)<br />
|-<br />
| 4 <br />
| 45ns (11.3)|| 46ns (11.5)|| 46ns (11.5) <br />
| 30ns (7.5)|| 30ns (7.5)|| 30ns (7.5)<br />
|-<br />
| 6 <br />
| 69ns (11.5)|| 70ns (11.7)|| 72ns (12.0) <br />
| 45ns (7.5)|| 46ns (7.7)|| 47ns (7.8)<br />
|- <br />
|}<br />
[1] Data in specification for 4.5V: Typical 15ns, Maximum 25ns<br><br />
[2] Data in specification for 6.0V: Typical 12ns, Maximum 21ns<br />
<br />
===DSP Library===<br />
<br />
----<br />
*Library functions in <dsp.h> include the following categories: <br />
#Vector<br />
#Window<br />
#Matrix<br />
#Filtering<br />
#Transform<br />
#Control<br />
<br />
====Data Types====<br />
*Signed Fractional Value (1.15 data format)<br />
**Inputs and outputs of the dsp functions adopt 1.15 data format, which consumes 16 bits to represent values between -1 to 1-2<sup>-15</sup> inclusive.<br />
**Bit<15> is a signed bit, positive = 0, negative = 1.<br />
**Bit<14:0> are the exponent bits ''e''.<br />
**Positive value = 1 - 2<sup>-15</sup>*(32768 - ''e'')<br />
**Negative value = 0 - 2<sup>-15</sup>*(32768 - ''e'')<br />
*40-bit Accumulator operations (9.31 data format)<br />
**The dsp functions use the 40 bits accumalators during arithmatic calculations.<br />
**Bit<39:31> are signed bits, positive = 0x000, negative = 0x1FF.<br />
**Bit<30:0> are exponent bits.<br />
*IEEE Floating Point Values<br />
**Fractional values can be converted to Floating point values using: '''fo = Fract2Float(fr);''' for fr = [-1, 1-2<sup>-15</sup>]<br />
**Floating point values can be converted to Fractional values using: '''fr = Float2Fract(fo);''' or '''fr = Q15(fo);''' for fo = [-1, 1-2<sup>-15</sup>]<br />
**Float2Fract() is same as Q15(), except having saturation control. When +ve >= 1, answer = 2<sup>15</sup>-1 = 32767 (0x7FFF). When -ve < -1, answer = -2<sup>15</sup> = -32767 (0x8000)<br />
<br />
===Build-in Library===<br />
<br />
----<br />
*Some assembler operators can only be accessed by inline assembly code, for example, <br />
#Manuipulation of accumulators A and B (add, sub, mul, divide, shift, clear, square)<br />
#Bit toggling<br />
#Access to psv (program space visiblity) page and offset<br />
#Access to table instruction page and offset<br />
*Built-in functions are written as C-like function calls to utilize these assembler operators.<br />
<br />
<br />
==Bootloader Development==<br />
<br />
===Concepts===<br />
*Programming with ICSP is useful when the target board is produced in batch. The producer can download a program even when the chip is on the target board.<br />
*However, ICSP requires an external programmer.<br />
*To allow the user to change the program after production but without the need of an external programmer, bootloader becomes useful.<br />
*Bootloader is a small program installed via ICSP. Everytime the device is reset, the bootloader is run first. The bootloader first detects the default serial channel whether the user wishes to download a new program to the device. If so, the bootloader will pause there, and wait for the user to download the hex file from the PC. The hex file is written to the device via RTSP instructions in the bootloader. If a new download is not necessary, the bootloader redirects to the previously installed user's program.<br />
*The disadvantage of bootloaders is that they consume some of the memory of the device.<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 7.1 Free bootloaders for dsPIC<br />
! Developer<br />
! Source<br />
! Platform<br />
! User Guide<br />
! Remarks<br />
|- valign="top"<br />
| [http://www.ingenia-cat.com/index.php?lang=en ingenia]<br />
| [http://www.ingenia-cat.com/download/iBL.s Assembly]<br />
| [http://www.ingenia-cat.com/download/ingeniadsPICbootloader1.1.zip Windows]<br />
| [http://www.ingenia-cat.com/reference/pdf/iBL.UG.V1.2.pdf pdf]<br />
| <br />
*Works for all dsPIC supporting RTSP<br />
*Auto baudrate detection<br />
*Use about 1.15% of the flash memory space (0xAFFF-0xAE00)/(0xAFFF-0x0100)<br />
*Development of Linux platform is underway<br />
*Modification of code for dsPIC30F5011 is successful<br />
|-valign="top"<br />
| [http://www.etc.ugal.ro/cchiculita/software/picbootloader.htm Tiny]<br />
| [http://www.etc.ugal.ro/cchiculita/software/tinybld191.zip Assembly]<br />
| Windows<br />
| [http://www.etc.ugal.ro/cchiculita/software/tinybldusage.htm Web]<br />
| <br />
*By default, only supports 601X, 601X, 401X, 2010<br />
*Smaller code size than ingenia, but not as easy to modify<br />
|-valign="top"<br />
| [http://www.via.si/software/dsPIC_bootloader/ Elektronika]<br />
| [http://www.via.si/software/dsPIC_bootloader/data/ Hex]<br />
| Windows<br />
| [http://www.via.si/software/dsPIC_bootloader/data/README.txt txt]<br />
| <br />
*Only works for dsPIC30F6014 serial port UART2 at baudrate 57600<br />
|-<br />
|}<br />
<br />
===dsPicBootloader===<br />
<br />
*The bootloader developed by ingenia is open source and it has been modified (see below) to suit our development using dsPic30f5011.<br />
*The bootloader (hereafter called dsPicBootloader) employs the following settings:<br />
# Use U2ART channel<br />
# Use FRC, PLL16<br />
# For 5011, the bootloader is located between 0x00AE00 to 0x00AFFE (512bytes). Refer to C:\Program Files\Ingenia\ingeniadsPICbootloader\ibl_dspiclist.xml after installing the GUI interface.<br />
*Changes made to [http://www.ingenia-cat.com/download/iBL.s assembly code] includes:<br />
1. including p30f5011.gld and p30f5011.inc<br />
.include "p30f5011.inc"<br />
2. changing the config code of UART #0x8420 -> #0x8020<br />
; Uart init<br />
mov '''#0x8020''', W0 ; W0 = 0x8020 -> 1000 0000 0010 0000b<br />
mov W0, U2MODE ; Enable UART, AutoBaud and 8N1<br />
clr U2STA<br />
3. changing the start address 0xAE00 - 0x0100 = 0AD00<br />
.equ CRC, W4<br />
.equ ACK, 0x55<br />
.equ NACK, 0xFF<br />
.equ USER_ADDRESS, 0x0100<br />
.equ START_ADDRESS, '''0xAD00''' ; Relative to 0x0100<br />
4. using Internal FRC and PLL16<br />
config __FOSC, CSW_FSCM_OFF & '''FRC_PLL16''' ;Turn off clock switching and<br />
;fail-safe clock monitoring and<br />
;use the Internal Clock as the<br />
;system clock<br />
5. disabling MCLR (optional)<br />
config __FBORPOR, PBOR_ON & BORV_27 & PWRT_16 & '''MCLR_DIS'''<br />
;Set Brown-out Reset voltage and<br />
;and set Power-up Timer to 16msecs<br />
6. changing all the related registers of U1ART to U2ART, all U1XXX => U2XXX<br />
'''U2MODE, U2STA, U2BRG, U2RXREG, U2TXREG'''<br />
7. changing all the related registers of IC1 to IC2, all IC1XXX => IC2XXX<br />
'''IC2CON, #IC2IF, #IC2IE'''<br />
<br />
===dsPicProgrammer (Java-based Multi-Platformed)===<br />
*Ingenia developed a programmer (PC-side) that works only in Windows environment. The project for Linux environment is currently suspended.<br />
*A simple programmer (hereafter called dsPicProgrammer) written in Java based on the library developed by [http://www.rxtx.org/ RXTX] has been developed here. The programmer supports both Linux and Windows environments, and may be used as a substitution for the official programmer developed by ingenia.<br />
*The programmer has the following specification and limitations:<br />
#Can be used on both Linux and Windows platforms.<br />
#Adjustable baudrate (9600bps to 57600bps).<br />
#Support programming of dsPIC30F5011 and dsPIC33FJ128GP306 devices (Developers may add your devices).<br />
#Protection against overwriting bootloader codes on devices.<br />
#Detection if application program does not have its reset() at user's code start address.<br />
#Reprogramming can be done without powering down the target board, provided the user's program is compliant to that stated below.<br />
#Target board will run the user's program after programming is done.<br />
#Can be used with USB-Serial Cables. Below is a list of tested cable:<br />
::[http://www.prolific.com.tw/eng/Products.asp?ID=59 Prolific PL-2303 USB to Serial Bridge Controller]: [http://www.prolific.com.tw/eng/downloads.asp?ID=31 Driver download]<br />
<br />
===Special Consideration===<br />
*The bootloader assumes that the user program starts at address 0x100. This is usually the case, but there are always exceptions.<br />
*To ensure that the user program always starts at address 0x100, you can create a customized linker script and customized reset() function as follows:<br />
:*Copy and modify the file named "crt0.s" from the directory "C:\Program Files\Microchip\MPLAB C30\src\pic30" to the project directory and include it.<br />
.section .reset, code //previously .section .libc, code <br />
:*Copy and modify the linkerscript for the device (e.g. p30f5011.gld) to the project directory and include it.<br />
.text __CODE_BASE :<br />
{<br />
*(.reset); //<-insert this line here<br />
*(.handle);<br />
*(.libc) *(.libm) *(.libdsp); /* keep together in this order */<br />
*(.lib*);<br />
*(.text);<br />
} >program<br />
<br />
===Communication Protocol===<br />
<br />
+-------------------+ +-------------------+----------------+<br />
| dsPicProgrammer | | dsPicBootloader | User's Program |<br />
+-------------------+ +-------------------+----------------+<br />
| PC | | Target dsPic |<br />
+-------------------+ +------------------------------------+<br />
| COM PORT |=============| UART |<br />
+-------------------+ +------------------------------------+<br />
<br />
* '''Stage 1: User's Configuation'''<br />
**Select a COM port channel<br />
**Select a baudrate<br />
**Select the user hex file<br />
java -jar dsPicProgrammer.jar COM1 19200 foo.hex<br />
* '''Stage 2: Resetting Target Device'''<br />
**dsPicProgrammer sends a Break character (pull UART-TX to low logic, which is normally high).<br />
**User's program on dsPic detects the break character and reset the chip<br />
::NOTE: The user's program is expected to have the following code in order to enable this function. Otherwise, the target board must be restarted manually.<br />
void _ISR _U2RXInterrupt(void)<br />
{<br />
//No Framming error<br />
if( U2STAbits.FERR == 0)<br />
{<br />
//Normal procedure<br />
}<br />
//Framming error<br />
else<br />
{<br />
if ( U2STAbits.URXDA ){<br />
unsigned char data;<br />
data = (unsigned char) U2RXREG;<br />
if(data == 0x00){<br />
// A break char has been received: <br />
// U2RX has been pulled to zero for more than 13 bits<br />
// This is used to reboot the pic<br />
mdelay(800); //wait for break character to clear<br />
asm("reset"); //software reset<br />
}<br />
} <br />
}<br />
_U2RXIF = 0; //Clear the flag<br />
}<br />
* '''Stage 3: Entering Ingenia's Protocol'''<br />
** Transmission is conducted in 8N1, i.e. 8-bit, no parity, 1 stop-bit<br />
** Communication Protocol is reviewed in [http://www.ingenia-cat.com/reference/pdf/iBL.UG.V1.2.pdf ingenia bootloader user's guide] section 2.1.3. The following summarises the key steps on the PC side (Refer also to section 2.2.2).<br />
::#Autobaud rate detection: dsPicProgrammer continuously sends a character "U" [0x55] via COM port and waits for an acknowledgment character "U", [ACK] = [0x55]<br />
::#Version Control: dsPicProgrammer sends the command character [0x03]. On success, dsPicProgrammer receives 3 characters i) Major Version ii) Minor Version iii) Acknowledgment [0x55]<br />
::#Device ID Monitoring: dsPicProgrammer sends the read command character [0x01] + 24-bit address [High][Medium][Low] (0xFF0000). Then, it receives 4-byte data [High][Medium][Low][ACK]<br />
::#Load the user hex file and check integrity<br />
::#Start Programming: dsPicProgrammer issues the write command character [0x02] + 24-bit address [High][Medium][Low]+ Number of bytes [N] + [data 0] + [data 1] + ... + [data N-1] + [CRC]=(INTEL HEX8 Checksum - Sum modulo 256) and receives [ACK] or [NACK] = [0xFF]<br />
::NOTE: Writing is in row mode access (i.e. erase and write a whole row, each row has 32 instructions, or 96 bytes because each instruction has 24 bits)<br />
* '''Stage 4: Goto User's Program'''<br />
**dsPicProgrammer sends the goto user code command [0x0F]<br />
<br />
<br />
==USB-RS232 Bridge==<br />
<br />
*As USB ports are becoming more and more common, COM ports and Parallel ports may be redundant in the next few years. This section explore the possibilities of programming the target board through a USB port.<br />
*There are two options:<br />
#Use an external USB/RS232 adaptor, the driver will emulate a virtual COM port, such as [http://www.prolific.com.tw/eng/downloads.asp?ID=31 Prolific] and [http://www.ftdichip.com/Drivers/VCP.htm FDTI]. Ingenia has tested its bootloader with some USB-232 manufacturers (silabs, FTDI, etc..). However, the programming failed with our Prolific adapter. Application program may use [http://java.sun.com/products/javacomm/ JavaComm API] (javax.comm) and/or [http://www.rxtx.org/ RXTX] to drive the COM port.<br />
#Modified the bootloader program on PC to support USB communication. e.g. using [http://jusb.sourceforge.net/ jUSB] and [http://javax-usb.org/ JSR-80] (javax.usb). External circuits such as PIC18F4550 and MAX232 are required.<br />
<br />
|--User's App.--|-------Device Manager------|-------USB-RS232 Interface------|---dsPIC---|<br />
Option 1:<br />
+-------------+ +----------+ +----------+ +---+ +------------+ +-----+ +--------+<br />
| Application |--| JavaComm |--| Virtual |==|USB|--| FDTI |--|RS232|==| Target |<br />
| Program | | RXTX | | COM Port | +---+ | Circuitary | +-----+ | Board |<br />
+-------------+ +----------+ +----------+ +------------+ +--------+<br />
Option 2:<br />
+-------------+ +--------+ +---+ +------------+ +-----+ +--------+<br />
| Application |----------| JSR-80 |==========|USB|--| PIC18F4550 |--|RS232|==| Target |<br />
| Program | | jUSB | +---+ | MAX232 | +-----+ | Board |<br />
+-------------+ +--------+ +------------+ +--------+<br />
<br />
*Currently, when RXTX is incorporated with JavaComm API, operating systems supported include Linux, Windows, Mac OS, Solaris and other operating systems. On the other hand, jUSB and JSR-80 only works for linux.<br />
<br />
===FDTI Chipset===<br />
*FT232RL communicates with PC via USB to provide 1 UART channel.<br />
*Datasheet can be downloaded [http://www.ftdichip.com/Documents/DataSheets/DS_FT232R.pdf here]. <br />
**Refer to Fig. 11 (Page 19) for Bus Powered Configuration.<br />
**Refer to Fig. 16 (Page 24) for for UART TTL-level Receive [RXD -> 1], Transmit [TXD -> 4], Transmit Enable [CBUS2/TXDEN -> 3]. Omit Receive Enable [CBUS3/PWREN#] and use [CBUS2/TXDEN -> 2] <br />
**Refer to Fig. 15 (Page 23) for LED Configuration: [CBUS0/TXLED#] and [CBUS1/RXLED#]<br />
*Virtual COM Port Drivers can be downloaded [http://www.ftdichip.com/Drivers/VCP.htm here].<br />
<br />
<br />
==Programming the Device==<br />
<br />
===Requirements===<br />
*Hardware<br />
#PC with COM port (Windows XP Installed for MPLAB)<br />
#ICD2 Programmer<br />
#Target Board<br />
#5V Power Supply<br />
<br />
*Software<br />
#[http://ww1.microchip.com/downloads/en/DeviceDoc/MP750.zip MPLAB IDE v7.50]: v7.60 is not compatible with our current [http://www.sure-electronics.com/ ICD2 Programmers]. There are consistent "Devices cannot be founded" warnings.<br />
#[http://chungyan5.no-ip.org/websvn/listing.php dsPicProgrammer] ('''dsPicProgrammer.jar''')<br />
#[http://users.frii.com/jarvi/rxtx/download.html RXTX driver]: download and upzip rxtx-2.1-7-bins-r2.zip (Final)<br />
<br />
*Files<br />
#[http://chungyan5.no-ip.org/websvn/listing.php dsPicBootloader] ('''bl_5011.hex'''). Original assembly code by ingenia can be downloaded from [http://www.ingenia-cat.com/download/iBL.s here].<br />
#Application hex file (e.g. '''app.hex''')<br />
<br />
===Loading Bootloader (Once only)===<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 9.1 Loading Bootloader<br />
! Step !! Remarks <br />
|-valign="top"<br />
| Install [http://ww1.microchip.com/downloads/en/DeviceDoc/MP750.zip MPLAB IDE] || <br />
*Do '''NOT''' connect ICD 2 (via USB) to PC<br />
*Execute '''MPLAB vX.XX Install.exe'''<br />
|-valign="top"<br />
| Install USB Driver ||<br />
*Follow the instruction in (C:\Program Files\Microchip\MPLAB IDE\ICD2\Drivers\Ddicd2.htm)<br />
|-valign="top"<br />
| Select Target Chip ||<br />
*Run MPLAB IDE on PC<br />
*Select: Configure>Select Devices...<br />
*Choose dsPIC30F5011<br />
|-valign="top"<br />
| Target <-> ICD 2 ||<br />
*Use six pin cable. Beware of the pin assignments. Only pin 1 - 5 should be used.<br />
*Place Jumper on target board (if any). The Jumper connects target V<sub>cc</sub> to ICD 2.<br />
*Do '''NOT''' power-up the target.<br />
|-valign="top"<br />
| ICD 2 <-> PC ||<br />
*Plug-in ICD 2 to PC via USB cable<br />
*Power-up the target.<br />
*Select: Programmer>Select Programmer>MPLAB ICD 2<br />
*If this is the first time the ICD 2 is connected to PC, MPLAB IDE will automatically download the required OS to ICD 2, wait until it has finished<br />
*If you have not connected and powered up the target, you might see Warnings on invalid device IDs, and/or running self tests.<br />
*See results of self test if necessary: Programmer>Settings, Status Tab. Refer to [http://ww1.microchip.com/downloads/en/DeviceDoc/51331B.pdf ICD2 User's Guide] Chapter 7.<br />
|-valign="top"<br />
| Load Bootloader ||<br />
*Select: File>Import...<br />
*Select '''bl_5011.hex'''<br />
|-valign="top"<br />
| Start Programming ||<br />
*Select: Programmer>Program<br />
|-valign="top"<br />
| Finishing ||<br />
*Power-down the Taget<br />
*Select: Programmer>Select Programmer>None<br />
*Unplug USB cable<br />
|-<br />
|}<br />
<br />
===Loading Firmware===<br />
====Java Environment Setup====<br />
*Download and install the latest JDK or JRE<br />
**Available from [http://java.sun.com/javase/downloads/index.jsp Sun Microsystems] (e.g. JDK 6 Update 3)<br>[[Image:1 1 java.JPG]]<br><br />
*Download and Extract RXTX Driver <br />
**Available from [http://users.frii.com/jarvi/rxtx/download.html RXTX] <br />
**File: rxtx-2.1-7-bins-r2.zip (Final)<br />
**Extract the files using software such as WinRAR<br>[[Image:1 2 rxtx.JPG]]<br><br />
*Copy RXTXcomm.jar<br />
**To C:\Program Files\Java\X\lib\ext (under the latest jre, e.g. X = jre1.6.0_03)<br>[[Image:1 3 rxtxcomm.JPG]]<br><br />
*Copy rxtxSerial.dll<br />
**To C:\Program Files\Java\X\bin (under the lastest jre, e.g. X = jre1.6.0_03)<br />
**For Linux users, copy librxtxSerial.so to /jre/lib/[machine type] (i386 for instance)<br>[[Image:1 4 rxtxserial.JPG]]<br><br />
*Download dsPicProgrammer <br />
**Available from [http://chungyan5.no-ip.org/websvn/listing.php?repname=repos+1&path=%2FdsPicProgrammer%2Ftags%2F&rev=0&sc=0 here]<br />
**Expand the latest tag under dsPicProgrammer<br />
**File: dsPicProgrammer.jar<br>[[Image:1 5 dspicprogrammer.JPG]]<br><br />
**Save the file (dsPicProgrammer.jar) and your hex file (foo.hex) to your local directory (e.g. C:\dsPicProgrammer\)<br>[[Image:1 6 dspicprogrammer2.JPG]]<br><br />
<br />
====Download Firmware====<br />
*Start a Command Prompt<br />
**Start -> Run<br>[[Image:2 1 run.JPG]]<br><br />
**Enter cmd<br>[[Image:2 2 cmd.JPG]]<br><br />
*Run dsPicProgrammer<br />
**Change to the directory where dsPicProgrammer.jar is located and run the command:<br>java -jar dsPicProgrammer.jar COM1 57600 foo.hex (Windows)<br>java -jar dsPicProgrammer.jar /dev/ttyS0 57600 foo.hex (Linux)<br>where COM1 is your COM Port ID<br>57600 is communication speed [in bps]<br>foo.hex is your firmware new file<br>[[Image:2 3 command.JPG]]<br><br />
**When the program prompt you for an input, press y:<br>[[Image:2 4 prompt.JPG]]<br><br />
**If communication can be established, you should see something like this:<br>[[Image:2 5 progress.JPG]]<br><br />
**Wait until programming is completed.<br>[[Image:2 6 complete.JPG]]<br><br />
====Troubleshooting====<br />
*Invalid COM Port<br />
**In case of selecting an invalid COM port, you should see the error message:<br>gnu.io.NoSuchPortException: Choosing COM Port Error<br>[[Image:3 1 com err.JPG]]<br><br />
*Missing firmware file<br />
**In case of selecting a firmware file that does not exist, you should see the error message:<br>java.io.FileNotFoundException: foo1.hex <The system cannot find the file specified><br>[[Image:3 2 file err.JPG]]<br><br />
*Missing RXTX driver<br />
**In case of missing the RXTX driver, you should see the error message:<br>Exception in thread “main” java.lang.NoClassDefFoundError: gnu/io/UnsupportedCommOperationException<br>[[Image:3 3 rxtx err.JPG]]<br><br />
<br />
<br />
==Remote Access==<br />
*At the moment, local devices (e.g. EEPROM, ADC, DAC, etc.) can only be accessed locally through POSIX functions such as open(), read(), write(), ioctl().<br />
*However, a client may need to access these devices on a remote server. This section reviews the background and gives some ideas on its possible implementation.<br />
<br />
===Requirements===<br />
*A remote file access protocol, to transfer "files" (i.e. device's data) such as:<br />
#[http://en.wikipedia.org/wiki/FTP File Transfer Protocol] (FTP): Required files are copied from sever to client for manipulation<br />
#[http://en.wikipedia.org/wiki/Remote_Shell Remote Shell] (RSH): Required files are copied from sever to client for manipulation<br />
#[http://en.wikipedia.org/wiki/Network_File_System_%28Sun%29 Network File System] (NFS): Required files are manipulated on sever<br />
*An API to access files using a selected protocol, such as:<br />
#[http://www.die.net/doc/linux/man/man2/lam_rfposix.2.html lam_rfposix]: A POSIX-like remote file service for Local Area Multicomputer<br />
#API employed by VxWorks: [http://en.wikipedia.org/wiki/VxWorks VxWorks] is a Unix-like real-time operating system, commonly used for embedded systems.<br />
<br />
===API Reference for VxWorks===<br />
*Reference:<br />
**[http://www.windriver.com/vxworks/ VxWorks Official Website]<br />
**[http://www-cdfonline.fnal.gov/daq/commercial/ OS Libraries API Reference]<br />
*Related Libraies<br />
**netDrv (netDrv.h): an API using FTP or RSH<br />
**nfsDrv (nfsDrv.h): an API using NFS<br />
<br />
<br />
==Conversion to dsPIC33F Devices==<br />
*This section discusses the conversion required from dsPIC30F5011 to dsPIC33FJ128GP306.<br />
*Refer to official document [http://ww1.microchip.com/downloads/en/DeviceDoc/70172A.pdf dsPIC30F to dsPIC33F Conversion Guidelines] (DS70172A).<br />
*Note that this section does not mainly intend to introduce the new functionalities of dsPIC33F devices. It only serves the purpose to summarise the major (if not minimum) changes required to port the setup of dsPIC30 to dsPIC33 devices.<br />
<br />
===Hardware===<br />
*dsPIC33 operates at voltage of 3.3V. A voltage regulator, such as [http://www.national.com/ds.cgi/LM/LM3940.pdf LM3940] can be used to convert 5V supply to 3.3V.<br />
*A 1uF capacitor has to be placed at pin 56 (previously V<sub>SS</sub>, now V<sub>DDCORE</sub>).<br />
<br />
===Software===<br />
<br />
====Configuration Bits====<br />
<br />
----<br />
*dsPIC33 can operate at 40MIPs at maximum. To configure the device using internal FRC, replace the configuration bits setting as follows:<br />
_FOSCSEL(FNOSC_FRCPLL); // FRC Oscillator with PLL<br />
_FOSC(FCKSM_CSDCMD & OSCIOFNC_ON & POSCMD_NONE); <br />
// Clock Switching and Fail Safe Clock Monitor is disabled<br />
// OSC2 Pin Function: OSC2(RC15) as Digital IO<br />
// Primary Oscillator Mode: Disabled<br />
_FWDT(FWDTEN_OFF); // Watchdog Timer Enabled/disabled by user software <br />
*Configure on-chip PLL at runtime as follows (at start of main function):<br />
_PLLDIV = 38; // M=40: PLL Feedback Divisor bits<br />
CLKDIV = 0; // N1=2: PLL VCO Output Divider Select bits<br />
// N2=2: PLL Phase Detector Input Divider bits<br />
OSCTUN = 22; // Tune FRC oscillator, if FRC is used; <br />
// 0: Center frequency (7.37 MHz nominal)<br />
// 22: +8.25% (7.98 MHz)<br />
RCONbits.SWDTEN = 0; // Disable Watch Dog Timer<br />
while(OSCCONbits.LOCK != 1); // Wait for PLL to lock<br />
<br />
====UART====<br />
<br />
----<br />
*No change is required.<br />
<br />
====I2C====<br />
<br />
----<br />
*dsPIC33 supports upto 2 I<sup>2</sup>C devices. As a result, replace all I<sup>2</sup>C related registers with xxI2Cyy to xxI2C'''1'''yy. For examples:<br />
_SI2C1IF = 0; //Clear Slave interrupt<br />
_MI2C1IF = 0; //Clear Master interrupt<br />
_SI2C1IE = 0; //Disable Slave interrupt<br />
_MI2C1IE = 0; //Disable Master interrupt<br />
I2C1BRG = I2C_BRG; // Configure Baud rate<br />
I2C1CONbits.I2CEN = 1;<br />
...<br />
etc.<br />
<br />
====ADC====<br />
<br />
----<br />
*The ADC in dsPic33 is significantly different from that in dsPic30. Specifically, ADC in dsPic33 uses DMA to buffer the adc data. Replace the open, interrupt routine, add and remove codes as follows:<br />
<br />
unsigned int adc_bufA[ADC_MAX_CH] __attribute__((space(dma),aligned(256)));<br />
unsigned int adc_bufB[ADC_MAX_CH] __attribute__((space(dma),aligned(256)));<br />
unsigned int* ADC16Ptr; //Pointer to ADC register buffer, <br />
unsigned char adc_ch_select = 0; //Pointer to channel to be read from<br />
unsigned char adc_data_ready = 0; //Indicate if RAM data is ready for output<br />
unsigned int which_dma = 0; //indicate which adc_buf to be used<br />
<br />
void adc_open(void)<br />
{<br />
// Configure interrupt<br />
_AD1IF = 0; //clear ADC interrupt flag<br />
_AD1IE = 0; //disable adc interrupt<br />
AD1CHSbits.CH0NA = 0;<br />
// Configure analog i/o <br />
_TRISB0 = 1;<br />
_TRISB1 = 1; <br />
AD1PCFG = 0xFFFC; //Enable AN0 (Vref+) and AN1 (Vref-)<br />
AD1PCFGH = 0xFFFF; //AN16-AN31: Disabled<br />
// Configure scan input channels <br />
AD1CSSL = 0x0003; //0 => Skip, 1 => Scan<br />
AD1CSSH = 0x0000; //Skipping AN16-AN31<br />
// ADCCON4:<br />
AD1CON4bits.DMABL = 0; // Each buffer contains 1 word<br />
// ADCCON3:<br />
AD1CON3bits.SAMC = 1; //1TAD for sampling time<br />
AD1CON3bits.ADRC = 0; //Use system clock<br />
AD1CON3bits.ADCS = ADC_ADCS; //each conversion requires 14TAD<br />
// ADCCON2:<br />
AD1CON2bits.VCFG = 3; //External Vref+, Vref-<br />
AD1CON2bits.CSCNA = 1; //Scan input<br />
AD1CON2bits.SMPI = 1; //2 channels are scanned<br />
// ADCCON1:<br />
AD1CON1bits.FORM = 0; //[0:integer]; [2 fractional]; [3 siged fractional]<br />
AD1CON1bits.SSRC = 7; //auto covert, using internal clock source<br />
AD1CON1bits.ASAM = 1; //auto setting of SAMP bit<br />
AD1CON1bits.AD12B = 1; //12-bit, 1-channel ADC operation<br />
AD1CON1bits.ADDMABM = 0; // DMA buffers are built in scatter/gather mode<br />
AD1CON1bits.ADON = 1; // Turn on the A/D converter<br />
// DMA0 Configuration:<br />
DMA0CONbits.AMODE = 2; // Configure DMA for Peripheral indirect mode<br />
DMA0CONbits.MODE = 2; // Configure DMA for Continuous Ping-Pong mode<br />
DMA0PAD=(int)&ADC1BUF0; <br />
DMA0CNT = 1; // generate dma interrupt every 2 samples <br />
// same as SMPI because only 1 dma buffer per channel <br />
DMA0REQ = 13; // Select ADC1 as DMA Request source<br />
DMA0STA = __builtin_dmaoffset(adc_bufA); <br />
DMA0STB = __builtin_dmaoffset(adc_bufB);<br />
_DMA0IF = 0; // Clear the DMA interrupt flag bit<br />
_DMA0IE = 1; // Set the DMA interrupt enable bit<br />
DMA0CONbits.CHEN=1; // Enable DMA<br />
}<br />
<br />
void _ISR _DMA0Interrupt(void)<br />
{<br />
ADC16Ptr = (which_dma == 0)? adc_bufA : adc_bufB; //Update pointer<br />
adc_data_ready = 1;<br />
which_dma ^= 1; //Next buffer to be used<br />
_DMA0IF = 0; //Clear the DMA0 Interrupt Flag<br />
}<br />
<br />
static void adcAdd(unsigned char ch){<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
TRISB = TRISB | mask;<br />
AD1CSSL = AD1CSSL | mask; <br />
AD1PCFG = ~AD1CSSL;<br />
AD1CON2bits.SMPI++; //take one more sample per interrupt<br />
DMA0CNT++; <br />
}<br />
<br />
static void adcRm(unsigned char ch){<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
AD1PCFG = AD1PCFG | mask;<br />
AD1CSSL = ~AD1PCFG;<br />
AD1CON2bits.SMPI--; //take one less sample per interrupt<br />
DMA0CNT--; <br />
}<br />
<br />
====EEPROM====<br />
<br />
----<br />
*There is no EEPROM in dsPIC33 devices. Please consider to use an external EEPROM using I<sup>2</sup>C communication.<br />
<br />
====Simple PWM====<br />
<br />
----<br />
*No change is required.<br />
<br />
===Memory Map for dsPIC33FJ128GP306===<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 11.1 Memory Location<br />
! Type !! Start Address !! End Address !! Size<br />
|-valign="top"<br />
| Flash || 0x000000 ||0x0157FF || 86K<sup>[1]</sup><br />
|-valign="top"<br />
| +--Flash: Reset Vector || 0x000000 ||0x000003 || 4<br />
|-valign="top"<br />
| +--Flash: Interrupt Vector Table || 0x000004 ||0x0000FF || 252<br />
|-valign="top"<br />
| +--Flash: Alternate Vector Table || 0x000104 ||0x0001FF || 252<br />
|-valign="top"<br />
| +--Flash: User Program || 0x000200 ||0x0157FF || 85.5K<br />
|-valign="top"<br />
| Programming Executive || 0x800000 || 0x800FFF || 4K<sup>[1]</sup><br />
|-valign="top"<br />
| Config Registers || 0xF80000 || 0xF80017 || 24<br />
|-valign="top"<br />
| Device ID (0xE5) || 0xFF0000 || 0xFF0003 || 4<br />
|-<br />
|}<br />
[1] Each address is 16-bit wide. Every two addresses correspond to a 24-bit instruction. Each even address contains 2 valid bytes; each odd address contains 1 valid byte plus 1 phathom byte.<br><br />
<br />
===Custom Linker Script to Maximize Space for Constant Data===<br />
*Constant data declared using keyword '''const''' will be stored in the .const section in the flash memory.<br />
*Normally, during compilation, the linker will assign these data after the program code (.text section).<br />
*Since .const is accessed by auto-psv function, to maximize the space for constant data (32kb), the .const section needs to be aligned at 0x80000 boundary.<br />
*This requires the following change in linker script:<br />
<br />
__CONST_BASE = 0x8000;<br />
<br />
.text __CODE_BASE :<br />
{<br />
*(.reset);<br />
*(.handle);<br />
*(.libc) *(.libm) *(.libdsp); /* keep together in this order */<br />
*(.lib*);<br />
/* *(.text); deleted to maximize space for const data */<br />
} >program<br />
<br />
.const __CONST_BASE :<br />
{<br />
*(.const);<br />
} >program<br />
<br />
*If your program is large, after this change in linker script, function calls may involve large jump in the memory map (>32kB). As a result, you may need to enable the large code and large memory model during compilation. In such case, use the following options in your build path:<br />
-mlarge-code -mlarge-data<br />
*Meanwhile, functions that are defined in the standard C libraries, but are replaced with your own implementations (e.g. I/O stubs: open(), read(), write(), lseek(), ioctl() etc.) may have the following linker error:<br />
/usr/pic30-elf/lib//libc-elf.a(fflush.eo)(.libc+0x3c): In function '.LM11':<br />
: Link Error: relocation truncated to fit: PC RELATIVE BRANCH _write<br />
/usr/pic30-elf/lib//libc-elf.a(fclose.eo)(.libc+0x42): In function '.LM18':<br />
: Link Error: relocation truncated to fit: PC RELATIVE BRANCH _close <br />
*To resolve the problem, you need to place the functions in the .libc section rather than in the .text section, like this:<br />
#define LIBC_CODE_LOC __attribute__ ( (section(".libc")))<br />
<br />
int LIBC_CODE_LOC open(const char *pathname, int flags){ ... }<br />
int LIBC_CODE_LOC close(int fd){ ... }<br />
int LIBC_CODE_LOC write(int fd, void* buf, int count) { ... }<br />
int LIBC_CODE_LOC read(int fd, void* buf, int count) { ... }<br />
int LIBC_CODE_LOC ioctl(int fd, int request, void* argp) { ... }<br />
int LIBC_CODE_LOC lseek(int fd, int offset, int whence) { ... }<br />
<br />
===dsPicBootloader and dsPicProgrammer===<br />
*RTSP for dsPIC33F is different from dsPIC30F.<br />
**Row size changes from 32 instructions (96bytes) to 64 instructions (192 bytes)<br />
**Erase operation changes from 1 row to 8 rows<br />
**No EEPROM<br />
*With regards to the above changes, dsPicBootloader and dsPicProgrammer has been modified. In particular, dsPicProgrammer can be used to program both dsPic30F and dsPic33F devices. You can easily add your devices to the source code.<br />
<br />
<br />
==Downloads==<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 12.1 Related software download links for dsPicBootloader and dsPicProgrammer<br />
! Program<br />
! Site 1<br />
! Site 2<br />
! Remarks<br />
|- valign="top"<br />
| JDK<br />
| [http://java.sun.com/javase/downloads/index.jsp website]<br />
| <br />
| Download latest JDK<br />
|- valign="top"<br />
| RXTX<br />
| [http://users.frii.com/jarvi/rxtx/download.html website]<br />
| <br />
| Download rxtx-2.1-7-bins-r2.zip or later<br />
|- valign="top"<br />
| dsPicBootloader v1.3<br />
| [http://chungyan5.no-ip.org/websvn/listing.php click]<br />
| [http://www.opencircuits.com/images/a/a7/DsPicBootloader_1_3_1.zip click]<br />
| Under "dsPicBootloader/", download bl_5011.s or bl_j128gp306.s<br />
|-valign="top"<br />
| dsPicProgrammer v1.3.5<br />
| [http://chungyan5.no-ip.org/websvn/listing.php click]<br />
| [http://www.opencircuits.com/images/9/9e/DsPicProgrammer_1_3_5.zip click]<br />
| Under "dsPicProgrammer/", dowload dsPicProgrammer.jar<br><br>Alternatively, if you want to compile yourself or modify the source code, download <br>all source files under "dsPicProgrammer/" '''plus''' RdFileIntelHex.java under <br>"IntelHexPaser/tags/0.02.00/".<br>You should also install RXTX on your local machine as recommended in the readme file.<br />
|- valign="top"<br />
| Ingenia's bootloader<br />
| [http://www.ingenia-cat.com/en/downloads.php website]<br />
| <br />
| Download original ingenia's bootloader<br />
|-<br />
|}</div>Yanhttp://www.opencircuits.com/index.php?title=DsPIC30F_5011_Development_Board&diff=12255DsPIC30F 5011 Development Board2007-12-24T08:41:15Z<p>Yan: /* Linux */ adding 2.00 installing procedure</p>
<hr />
<div>==Introduction==<br />
<br />
===Features of dsPIC30F5011===<br />
*2.5 to 5V <br />
*Up to 30MIPs<br />
*High current/sink source I/O pins: 25mA<br />
*DSP Instruction Set<br />
*Dual programming techniques: ICSP and RTSP<br />
*UART: up to 2 modules<br />
*I<sup>2</sup>C: up to 1Mbps<br />
*10-bit A/D, 1.1 Msps <br />
*12-bit A/D, 200 ksps<br />
*44K flash (66Kb), 4Kb RAM, 1Kb EEPROM<br />
*No DAC<br />
*Pin-to-pin compatible with other dsPICs<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 1.1 Comparison with Compatible dsPICs<br />
! dsPic !! Price<br>US$ !! MIPs<br />
! Flash<br>(kB)!! RAM<br>(kB) !! EEPROM<br>(kB)<br />
! I/O !! ADC<br>12-bit !! IC !! OC !! Motor<br>Ctrl !! Timers<br />
! QEI !! UART !! SPI !! I2C !! CAN !! Codec<br />
|- <br />
| 30F5011 || 5.91 || 30<br />
| 66 || 4 || 1<br />
| 52 || 16 || 8 || 8 || 0 || 5x16bit<br>2x32bit<br />
| 0 || 2 || 2 || 1 || 2 || 1<br />
|-<br />
| 30F6011A || 7.73 || 30<br />
| 132 || 6 || 2<br />
| 52 || 16 || 8 || 8 || 0 || 5x16bit<br>2x32bit<br />
| 0 || 2 || 2 || 1 || 2 || 0<br />
|-<br />
| 30F6012A || 7.85 || 30<br />
| 144 || 8 || 4<br />
| 52 || 16 || 8 || 8 || 0 || 5x16bit<br>2x32bit<br />
| 0 || 2 || 2 || 1 || 2 || 1<br />
|- <br />
| 33FJ128GP206 || 4.62 || 40<br />
| 128 || 8 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 1 || 0 || 1<br />
|-<br />
| 33FJ128GP306 || 4.81 || 40<br />
| 128 || 16 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 2 || 0 || 1<br />
|-<br />
| 33FJ128GP706 || 5.49 || 40<br />
| 128 || 16 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 2 || 2 || 1<br />
|-<br />
| 33FJ128MC506 || 4.97 || 40<br />
| 128 || 8 || 0<br />
| 53 || 16 || 8 || 8 || 8 || 9x16bit<br>4x32bit<br />
| 1 || 2 || 2 || 2 || 1 || 0<br />
|-<br />
| 33FJ128MC706 || 5.38 || 40<br />
| 128 || 16 || 0<br />
| 53 || 16 || 8 || 8 || 8 || 9x16bit<br>4x32bit<br />
| 1 || 2 || 2 || 2 || 1 || 0<br />
|-<br />
| 33FJ256GP506 || 6.11 || 40<br />
| 256 || 16 || 0<br />
| 53 || 18 || 8 || 8 || 0 || 9x16bit<br>4x32bit<br />
| 0 || 2 || 2 || 2 || 1 || 1<br />
|-<br />
|}<br />
<br />
===Web Page===<br />
*[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2529&param=en024856 Microchip Official Website]<br />
<br />
===Forum===<br />
*[http://direct.forum.microchip.com/default.aspx Microchip]: Official forum by Microchip<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=49 MPLAB ICD 2]: Subforum on ICD 2 programmer<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=57 MPLAB IDE]: Subforum on IDE<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=101 MPLAB C30 Compiler, ASM30, Link30 forum]: Subforum on C compiler. Refer to [http://ww1.microchip.com/downloads/en/DeviceDoc/C30_Users_Guide_51284e.pdf MPLAB C30 C Compiler User's Guide] Chapter 3<br />
**[http://direct.forum.microchip.com/tt.aspx?forumid=153 dsPIC30F Topics]: Subformum on dsPIC30F<br />
*[http://www.gnupic.org/ GNUPIC]: Discussion on PIC in Linux Systems<br />
**[http://www.linuxhacker.org/cgi-bin/ezmlm-cgi?1:dds:5443#b Debian]<br />
*[http://www.htsoft.com/forum/all/ubbthreads.php/Cat/0/C/6 HI-TECH Software Forum]: Discussion on dsPICC, a C compiler developed by HI-TECH<br />
*[http://piclist.com/techref/piclist/index.htm PICList]: Discussion on older PIC systems (not dsPIC)<br />
*[http://groups.google.com/group/pickit-devel PicKit]: Discussion on PICkit/PICkit 2 programmers<br />
*[http://sourceforge.net/forum/forum.php?forum_id=382005 FreeRTOS Real Time Kernel]: Open Discussion and Support on FreeRTOS <br />
<br />
===References===<br />
*dsPIC30F<br />
**[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2574 dsPIC30F Family Reference Manual Sections]: Contains detailed descriptions on dsPIC30F register definitions and example codes<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80169E.pdf dsPIC30F Family Reference Manual Errata (Use with revision 70046B only)]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70116F.pdf dsPIC30F5011, dsPIC30F5013 Data Sheet]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80210e.pdf dsPIC30F5011/5013 Rev. A1/A2 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80223D.pdf dsPIC30F5011/5013 Rev. A3 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70102G.pdf Flash Programming Specification]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70157B.pdf dsPIC30F Programmer's Reference Manual]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80170a.pdf dsPIC30F Programmer's Reference Manual Errata (use with revision DS70030E only)]<br />
<br />
*dsPIC33F<br />
**[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2573 dsPIC33F Family Reference Manual Sections]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70165E.pdf dsPIC33F Family Data Sheet]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80279B.pdf dsPIC33F Rev. A2 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/80306A.pdf dsPIC33FJXXXGPX06/X08/X10 Rev. A2 Silicon Errata]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70152C.pdf Flash Programming Specification]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/70172A.pdf dsPIC30F to dsPIC33F Conversion Guidelines]<br />
*ICD2 Programmer<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/51331B.pdf ICD2 User's Guide] <br />
*MPLAB<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/51519B.pdf MPLAB IDE User's Guide]<br />
*C30 Compiler<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/C30_Users_Guide_51284e.pdf MPLAB C30 C Compiler User's Guide]: Contains commands for using pic30-elf-gcc <br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/16bit_Language_Tool_Libraries_51456c.pdf 16-bit Language Tools Libraries]: Contains summaries and examples of using DSP libraries, standard C libraries and device libraries<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/Asm30_Link_Util_51317e.pdf MPLAB ASM30, MPLAB LINK30 and Utilities User's Guide]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/51322d.pdf dsPIC30F Language Tools Quick Reference Card]<br />
<br />
===Code Examples===<br />
*[http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1408 Microchip Example Codes for dsPic]<br />
<br />
<br />
==Programming Methods==<br />
*There are 2 programming methods: In-Circuit Serial Programming (ICSP) and Run-Time Self-Programming (RTSP)<br />
*ICSP allows the devices to be programmed after being placed in a circuit board.<br />
*RTSP allows the devices to be programmed when an embedded program is already in operation.<br />
<br />
===ICSP: External Programmer (ICD2)===<br />
*Two types of ICSP are available: '''ICSP''' and '''Enhanced ICSP'''. Both of them require setting MCLR# to V<sub>IHH</sub> (9V – 13.25V).<br />
*Standard ICSP<br />
**Use external programmer (e.g. MPLAB<sup>®</sup> ICD 2, MPLAB<sup>®</sup> PM3 or PRO MATE<sup>®</sup> II) only.<br />
**Required low-level programming to erase, program and verify the chip.<br />
**Slower, because codes are serially executed.<br />
**Program memory can be erased using ''Normal-Voltage'' (4.5 – 5.5V) or ''Low-Voltage'' (2.5V – 4.5V).<br />
<br />
*Enhanced ICSP<br />
**Use external programmer and '''Programming Executive''' (PE).<br />
**PE is stored in the on-chip memory.<br />
**PE allows faster programming.<br />
**PE can be downloaded to the chip by external programmer using the standard ICSP method.<br />
**PE contains a small command set to erase, program and verify the chip, avoiding the need of low-level programming.<br />
<br />
====Hardware Interface====<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.1 Pin Used by ICSP<br />
! Pin Label !! Function !! Pin Number<br />
|- <br />
| MCLR# || Programming Enable|| 7<br />
|-<br />
| V<sub>DD</sub> || Power Supply || 10, 26, 38, 57<br />
|-<br />
| V<sub>SS</sub> || Ground || 9, 25, 41, 56<br />
|- <br />
| PGC || Serial Clock || 17<br />
|-<br />
| PGD || Serial Data || 18<br />
|-<br />
|}<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.2 Available Programmers in the Market<br />
! Product Name<br />
! Interface with PC<br />
! Interface with Device<br />
! Price (US)<br />
! Postage (US)<br />
! Total (US)<br />
|- <br />
| [http://direct.www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en010046&part=DV164005 MPLAB<sup>®</sup> ICD 2]<br />
| USB or RS232<br />
| [http://www.microchip.com/Microchip.WWW.SecureSoftwareList/secsoftwaredownload.aspx?device=en010046&lang=en&ReturnURL=http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en010046&part=DV164005# 6-PIN RJ-12 connector]<br />
| $159.99<br />
| -<br />
| -<br />
|-<br />
| [http://www.etekronics.com/product_info.php?cPath=24&products_id=48 Full Speed USB Microchip ICD2<br> Debugger and Programmer]<br />
| USB<br />
| 6-PIN ICSP connector<br>6-PIN RJ-12 connector<br />
| $72.00<br />
| $12.00<br />
| $84.00<br />
|-<br />
| [http://www.etekronics.com/product_info.php?cPath=24&products_id=47 Mini Microchip Compatible ICD2<br> Debugger and Programmer]<br />
| RS232<br />
| 6-PIN ICSP connector<br>6-PIN RJ-12 connector<br />
| $45.00<br />
| $10.00<br />
| $55.00<br />
|-<br />
| [http://www.inexglobal.com/microcontroller.php ICDX30]<br />
| RS232<br />
| 6-pin RJ-11<br />
| $51.00<br />
| $47.46<br />
| $98.46<br />
|-<br />
| *[http://www.sure-electronics.net Clone Microchip ICD2] (Now Using)<br />
| USB<br />
| 6-pin flat cables<br />
| $30.00<br />
| $12.00<br />
| $42.00<br />
|-<br />
|}<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.3 DIY ICD 2 Programmer Circuit<br />
! Source !! Schematic !! PIC16F877A Bootloader<br />
|- <br />
| [http://membres.lycos.fr/silicium31/Electronique/PIC/FreeIcdEnglish.htm Patrick Touzet]<br />
| [http://membres.lycos.fr/silicium31/Electronique/PIC/ICD2%20V1.3.pdf Yes]<br />
| [http://membres.lycos.fr/silicium31/Electronique/PIC/ICD2_FW.zip HEX]<br />
|-<br />
| [http://www.nebadje.org/doku.php?id=neblab:icd2clone Nebadje]<br />
| [http://people.ee.ethz.ch/~jbiveron/nebadje/ICD2_DOC.pdf Yes]<br />
| [http://people.ee.ethz.ch/~jbiveron/nebadje/ICD2_FW.zip Zip]<br />
|-<br />
|}<br />
<br />
====Software Interface====<br />
*The program can be written and compiled in an Integrated Development Environment (IDE) using either Assembly or C. The complied codes are then loaded to the device through the external programmer.<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 2.4 Summary of IDE<br />
! Product Name !! Features !! OS !! Price (US$)<br />
|- <br />
| [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en019469&part=SW007002 MPLAB<sup>®</sup> IDE]<br />
| Assembler Only<br />
| Windows<br />
| Free<br />
|-<br />
| [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en010065&part=SW006012 MPLAB<sup>®</sup> C30]<br />
| Assembler and C-Compiler<br />
| Windows<br />
| $895.00 (Free student version<sup>1</sup>)<br />
|-<br />
| [http://linux.softpedia.com/get/Science-and-Engineering/Electronic-Design-Automation-EDA-/Piklab-8099.shtml Piklab 0.12.0]<br />
| Assembler and C-Compiler<br />
| Linux<br />
| Free<sup>2</sup><br />
|}<br />
# Full-featured for the first 60 days. After 60 days, some code optimization functions are disabled. The compiler will continue to function after 60 days, but code size may increase.<br />
# The current version supports external programmer ICD 2, but not yet tested.<br />
<br />
===RTSP: COM Port (Bootloader)===<br />
*RTSP works in normal voltage (MCLR# no need to raise to V<sub>IHH</sub>).<br />
*No literature has mentioned the incorporation of Programming Executive (PE). Presumably, since Enhanced ICSP needs to set MCLR# to V<sub>IHH</sub>, RTSP cannot use PE.<br />
*Refer to [http://www.opencircuits.com/DsPIC30F_5011_Development_Board#Bootloader_Development bootloader section].<br />
<br />
<br />
==IC Requirements==<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 3.1 IC Requirements<br />
! Part No. !! Description <br />
! Min Temp !! Max Temp !! Min Volt !! Max Volt !! Typ Cur !! Max Cur<br />
|-valign="top"<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/70116F.pdf dsPIC30F5011-30I/PT] || uP <br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 2.5V <sup>[1]</sup>|| 5.5V<br />
| 145mA || 217mA<br />
|-<br />
| [http://datasheets.maxim-ic.com/en/ds/MAX3222-MAX3241.pdf MAX3232ESE] || RS232 driver<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 3.0V || 5.5V<br />
| 0.3mA || 1.0mA<br />
|-<br />
| [http://www.national.com/ds.cgi/DS/DS3695.pdf DS3695N] || RS485 driver<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 4.75V || 5.25V<br />
| 42mA || 60mA<br />
|-<br />
| [http://focus.ti.com/lit/ds/symlink/dac6574.pdf DAC6574IDGS] || 10-bit Quad-DAC I<sup>2</sup>C<br />
| -40<sup>o</sup>C || 105<sup>o</sup>C<br />
| 2.7V || 5.5V<br />
| 0.6mA || 0.9mA<br />
|-<br />
| [http://www.semiconductors.philips.com/acrobat/datasheets/74HC_HCT14_3.pdf 74HC14D] || Quad-Schmitt Trigger<br />
| -40<sup>o</sup>C || 125<sup>o</sup>C<br />
| 2.0V || 6.0V<br />
| || 0.02mA<br />
|-<br />
| '''Overall''' || <br />
| '''-40<sup>o</sup>C''' || '''85<sup>o</sup>C'''<br />
| '''4.75V''' || '''5.25V'''<br />
| || '''<300mA <sup>[2]</sup>'''<br />
|-<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/70165E.pdf dsPIC33FJ128GP306-I/PT] || uP <br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 3.0V <sup>[1]</sup>|| 3.6V<br />
| 74mA || 250mA<br />
|-<br />
| [http://www.analog.com/UploadedFiles/Data_Sheets/ADM3485E.pdf ADM3485EARZ] || RS485 driver<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 3.0V || 3.6V<br />
| 1.1mA || 2.2mA<br />
|-<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/21203N.pdf 24LC256-I/SN] || 256kBits I2C EEPROM<br />
| -40<sup>o</sup>C || 85<sup>o</sup>C<br />
| 2.5V || 5.5V<br />
| 400uA || 3mA<br />
|-<br />
| [http://www.national.com/ds.cgi/LM/LM3940.pdf LM3940IMP-3.3] || 5V-3.3V Regulator<br />
| -40<sup>o</sup>C || 125<sup>o</sup>C<br />
| 5.0V || 7.5V<br />
| 10mA || 250mA<br />
|-<br />
|}<br />
#Minimum voltage measured is 3.3V (with 2 LEDs blinking) running at 30MHz.<br />
#Measured current at 5V is 180mA (with 2 LEDs blinking only)<br />
<br />
<br />
==Development Environment==<br />
<br />
===Windows===<br />
<br />
[[Image:PIC_setup_win.JPG]]<br />
<br />
*C-Compiler, Assembler and Linker are under GNU license.<br />
**MPLAB C30 C Compiler (*.c -> *.s)<br />
**MPLAB ASM30 Assembler (*.s -> *.o)<br />
**MPLAB LINK30 Linker (*.o -> *.bin)<br />
<br />
*PA optimizer, simulator, runtime libraries, header files, include files, and linker scripts are not covered by GNU. Reference is [http://direct.forum.microchip.com/tm.aspx?m=107208 here].<br />
<br />
*Microchip has integrated ASM30, LINK30, assembly header files, linker scripts in MPLAB IDE, which is free for download.<br />
*MPLAB C30 costs US$895. A 60-day free student version is also available. After 60-days, the optimizer is automatically disabled, while other tools can still function properly. Refer to Table 2.4.<br />
<br />
*C-libraries contained in C30 includes (Refer to [http://ww1.microchip.com/downloads/en/DeviceDoc/16bit_Language_Tool_Libraries_51456c.pdf 16-Bit Language Tools Libraries] from Microchip).<br />
<br />
<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 4.1 C Libraries in MPLAB C30<br />
! Library !! Directory <br>(\\Microchip\MPLAB C30) !! Major functions<br />
|-valign="top"<br />
| DSP Library <br>(e.g. libdsp-coff.a)<br />
| \lib <br> \src\dsp <br> \support\h<br />
| Vector, Matrix, Filter, etc.<br />
|-valign="top"<br />
| 16-Bit Peripheral Libraries <br>(e.g. libp30F5011-coff.a)<br />
| \lib <br> \src\peripheral <br> \support\h<br />
| ADC12, IOPort, UART, I<sup>2</sup>C, etc.<br />
|-valign="top"<br />
| Standard C Libraries <br>(e.g. libc-coff.a, libm-coff.a, libpic-coff.a)<br />
| \lib <br> \src\libm <br> \include<br />
| stdio.h, time.h, float.h, math.h, <br />
|-valign="top"<br />
| MPLAB C30 Built-in Functions<br />
| none<br />
| _buildin_addab, _buildin_add, _buildinmpy, etc<br />
|-<br />
|}<br />
<br />
===Linux===<br />
<br />
[[Image:PIC_setup_linux.JPG]]<br />
<br />
*C Compiler, Assembler and Linker are under GNU license.<br />
**The code can be downloaded from Microchip at [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en023073 here].<br />
**Current MPLAB ASM30 Assembler: v2.04<br />
**Current MPLAB C30 Compiler: v2.04<br />
<br />
*[http://gcc.gnu.org/ml/gcc/2005-02/msg01144.html John Steele Scott] has made templates that can be readily used by Debian-based systems. <br />
*For v1.32, the necessary conversion to *.deb has been done already at [http://noel.feld.cvut.cz/dspic/ here].<br />
**Download '''pic30-1.32-debian.tar.bz2''' for Template v1.32.<br />
**Download '''pic30-binutils_1.32-1_i386.deb''' for the assember.<br />
**Download '''pic30-gcc_1.32-1_i386.deb''' for the compiler.<br />
*For v2.00<br />
**goto http://www.baycom.org/~tom/dspic/<br />
**download pic30-gcc-2.00-1.i386.rpm and pic30-binutils-2.00-1.i386.rpm<br />
**convert to deb files<br />
**install these two deb files<br />
*For v3.01, convert the Toolchain following instructions at [http://www.nabble.com/Debian-templates-for-dsPIC-build-toolchain-3.01-tf4308624.html here]<br />
**pre-install these packages: dpkg-dev, debhelper, bison, flex, sysutils, gcc-3.3, fakeroot<br />
**pack pic30-binutils into deb file<br />
**install pic30-binutils<br />
**pack pic30-gcc-3.01 into deb file<br />
**install pic30-gcc-3.01<br />
**pack pic30-support into deb file<br />
**install pic30-support<br />
*'''Important Note''': Only the compiler is free. The header files and library are owned by Microchip. <br />
**Thomas Sailer suggested to download the Student version of C30 compiler and then build the libraries without source code. A package template for Fedora system is available [http://www.baycom.org/~tom/dspic/ here].<br />
**Instructions for filling the upstream direction is available [http://forum.microchip.com/printable.aspx?m=139360 here].<br />
**Alteratively, [https://gna.org/projects/pic30-libc/ Stephan Walter] has started a project to develop C Runtime Library for dsPIC. <br />
***Current libraries in version 0.1.1 include: assert.h, cdefs.h, ctype.h, errno.h, inttypes.h, stdint.h, stdio.h, stdlib.h, string.h<br />
<br />
*Burning Program Codes to Target Board<br />
#Use 'dspicprg and dspicdmp' utilities developed by [http://homerreid.ath.cx/misc/dspicprg/ Homer Reid] to burn hex code (*.hex) to devices. See Reference [http://forum.microchip.com/tm.aspx?m=94243 here]. Through serial port only?<br />
#Use [http://piklab.sourceforge.net/ Piklab IDE]. Details on file format not known.<br />
#Use [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en019469&part=SW007002 MPLAB IDE] to burn hex code (*.hex) to devices.<br />
<br />
===Code Optimization===<br />
*Below is a comparsion between different optimization levels for the project including drivers for 2 projects.<br />
<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 4.2 Comparison between differnt optimization levels<br />
! Optimization !! Description !! Project 1<br>Code Size<br>(byte) !! Project 1<br>Data Usage<br>(byte) !! Project 2<br>Code Size<br>(byte) !! Project 2<br>Data Usage<br>(byte)<br />
|-valign="top"<br />
| O0 <br />
| No optimization<br>Fastest Compilation<br />
| 6222 (9%) || 178 (4%) || 26,037 (38%) || 710 (17%)<br />
|-valign="top"<br />
| O1 <br />
| Optimize<br> Tries to reduce code size and execution time.<br />
| 4473 (6%) || 178 (4%) || 22,290 (32%) || 710 (17%)<br />
|-valign="top"<br />
| O2 <br />
| Optimize even more<br> Performs nearly all supported optimizations <br>that do not involve a space-speed trade-off. <br>Increases both compilation time and the <br>performance of the generated code.<br />
| 4422 (6%) || 178 (4%) || 21,993 (32%) || 710 (17%)<br />
|-valign="top"<br />
| O3 <br />
| Optimize yet more. <br>O3 turns on all optimizations specified by O2 <br>and also turns on the inline-functions option.<br />
| 4485 (6%) || 178 (4%) || 22,176 (32%) || 710 (17%)<br />
|-valign="top"<br />
| Os <br />
| Optimize for size. <br>Os enables all O2 optimizations that do not <br>typically increase code size. It also performs <br>further optimizations designed to reduce code <br>size.<br />
| 4356 (6%) || 178 (4%) || 21,885 (32%) || 710 (17%)<br />
|-<br />
|}<br />
<br />
<br />
==Software Architecture==<br />
+--------+--------+--------+--------+--------+<br />
Application | Task 1 | Task 2 | Task 3 | Task 4 | Task 5 |<br />
+--------+--------+--------+--------+--------+<br />
| POSIX API |<br />
+-------------------+------------------------+<br />
OS | Coroutine | FreeRTOS Scheduler |<br />
+-------------------+------------------------+<br />
| Drivers |<br />
+------+-----+-----+--------+-------+--------+<br />
Hardware | UART | ADC | DAC | EEPROM | PWM | TIMERS | <br />
+------+-----+-----+--------+-------+--------+<br />
*Currently, operating system is based on [http://www.freertos.org/ FreeRTOS] incorporating coroutine developed by [http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html Simon Tatham]<br />
*Software Drivers are to be developed to allow users at Application Level to use the hardware (e.g. ADC, DAC, UART, EEPROM etc) through the OS.<br />
*The interface between the drivers and the OS is based on [http://www.die.net/doc/linux/man/man2/ POSIX standard] (e.g. open(), write(), read(), ioctl(), usleep() etc).<br />
*The most up-to-date development can be found at repository [http://chungyan5.no-ip.org/vc/?root=freertos_posix freertos_posix]<br />
<br />
<br />
==Programming Tips==<br />
<br />
===Memory Map for 5011===<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 6.1 Memory Location<br />
! Type !! Start Address !! End Address !! Size<br />
|-valign="top"<br />
| Flash || 0x000000 ||0x00AFFF || 44K<sup>[1]</sup><br />
|-valign="top"<br />
| +--Flash: Reset Vector || 0x000000 ||0x000003 || 4<br />
|-valign="top"<br />
| +--Flash: Interrupt Vector Table || 0x000004 ||0x00007F || 124<br />
|-valign="top"<br />
| +--Flash: Alternate Vector Table || 0x000084 ||0x0000FF || 124<br />
|-valign="top"<br />
| +--Flash: User Program || 0x000100 ||0x00AFFF || 43.7K<br />
|-valign="top"<br />
| EEPROM || 0x7FFC00 || 0x7FFFFF || 1K<sup>[2]</sup><br />
|-valign="top"<br />
| Programming Executive || 0x800000 || 0x8005BF || 1472<br />
|-valign="top"<br />
| Unit ID || 0x8005C0 || 0x8005FF || 64<br />
|-valign="top"<br />
| Config Registers || 0xF80000 || 0xF8000F || 16<br />
|-valign="top"<br />
| Device ID || 0xFF0000 || 0xFF0003 || 4<br />
|-<br />
|}<br />
[1] Each address is 16-bit wide. Every two addresses correspond to a 24-bit instruction. Each even address contains 2 valid bytes; each odd address contains 1 valid byte plus 1 phathom byte.<br><br />
[2] Each address is 8-bit wide.<br />
<br />
===Data Location===<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 6.2 Data Location<br />
! Type !! Description !! Example<br />
|-valign="top"<br />
| _XBSS(N) <sup>[1]</sup><br />
| RAM Data in X-memory, aligned at N, no initilization<br />
| int _XBSS(32) xbuf[16];<br />
|-valign="top"<br />
| _XDATA(N) <sup>[1]</sup><br />
| RAM Data in X-memory, aligned at N, with initilization<br />
| int _XDATA(32) xbuf[] = {1, 2, 3, 4, 5};<br />
|-valign="top"<br />
| _YBSS(N) <sup>[1]</sup><br />
| RAM Data in Y-memory, aligned at N, no initilization<br />
| int _YBSS(32) ybuf[16];<br />
|-valign="top"<br />
| _YDATA(N) <sup>[1]</sup><br />
| RAM Data in Y-memory, aligned at N, with initilization<br />
| int _YDATA(32) ybuf[16] = {1, 2, 3, 4, 5};<br />
|-valign="top"<br />
| __attribute__((space(const)))<br />
| Flash ROM data, constant, accessed by normal C<br>statements, but 32K max.<br />
| int i __attribute__((space(const))) = 10;<br />
|-valign="top"<br />
| __attribute__((space(prog)))<br />
| Flash ROM data, read/write by program space visibility<br>window (psv)<br />
| int i __attribute__((space(prog)));<br />
|-valign="top"<br />
| __attribute__((space(auto_psv)))<br />
| Flash ROM data, read by normal C statements, write<br>by accessing psv<br />
| int i __attribute__((space(auto_psv)));<br />
|-valign="top"<br />
| __attribute__((space(psv)))<br />
| Flash ROM data, read/write by (psv)<br />
| int i __attribute__((space(psv)));<br />
|-valign="top"<br />
| _EEDATA(N) <sup>[1]</sup><br />
| ROM Data in EEPROM, aligned at N, read/write with psv<br />
| int _EEDATA(2) table[]={0, 1, 2, 3, 5, 8};<br />
|-valign="top"<br />
| _PERSISTENT<br />
| RAM Data, data remain after reset<br />
| int _PERSISTENT var1, var2;<br />
|-valign="top"<br />
| _NEAR<br />
| RAM Data at near section<br />
| int _NEAR var1, var2;<br />
|-valign="top"<br />
| _ISR<br />
| Interrupt service rountine<br />
| void _ISR _INT0Interrupt(void);<br />
|-valign="top"<br />
| _ISRFAST<br />
| Fast interrupt service rountine<br />
| void _ISRFAST _T0Interrupt(void);<br />
|-<br />
|}<br />
#N must be a power of two, with a minimum value of 2.<br />
<br />
===Configuration Bits===<br />
----<br />
*System clock source can be provided by:<br />
#Primary oscillator (OSC1, OSC2)<br />
#Secondary oscillator (SOSCO and SOSCI) with 32kHz crystal<br />
#Internal Fast RC (FRC) oscillator at 7.37MHz (7372800Hz)<br />
#Low-Power RC (LPRC) oscillator (Watchdog Timer) at 512 kHz.<br />
*These clock sources can be incorporated with interal Phase-locked-loop (PLL) x4, x8 or x16 to yield the osciallator frequrence F<sub>OSC</sub><br />
*The system clock is divided by 4 to yield the internal instruction cycle clock, F<sub>CY</sub>=F<sub>OSC</sub>/4<br />
*FRC with PLLx16 is used to achieve F<sub>CY</sub>=29.49MHz (29491200Hz or 30MIPS)<br />
<br />
//The code (MACRO) below is to be placed at the top of program (before main)<br />
_FOSC(CSW_FSCM_OFF & FRC_PLL16);<br />
_FWDT(WDT_OFF); //Turn off Watchdog Timer<br />
_FBORPOR(PBOR_ON & BORV_27 & MCLR_DIS & PWRT_16);<br />
_FGS(CODE_PROT_OFF); //Disable Code Protection<br />
<br />
===Timer===<br />
<br />
----<br />
*Each timer is 16-bit (i.e. counting from 0 to 65535).<br />
*Timer 2 and 3 can be incorporated together to form a 32-bit timer.<br />
*Prescale is the ratio between timer counts and system clock counts. Prescales of 1:1, 1:8, 1:64 and 1:256 are available.<br />
*Timers may be used to implement free time clock or mesaure time.<br />
<br />
====Free Time Clock====<br />
*Let required time for ticking be PERIOD.<br />
*Number of instruction cycles during PERIOD = PERIOD*F<sub>CY</sub> cycles<br />
*Using a prescale of 1:x, the timer period count register = # of cycles/x<br />
*e.g. PERIOD = 10ms; # of cycles = 10ms*30MHz = 300000 cylces; Using 1:64 Prescale, register setting = 300000/64 = 4688<br />
void time_init(void){<br />
TMR1 = 0; // Clear register<br />
PR1 = 4688; // Set period<br />
//============================================================<br />
_T1IF = 0; // Clear interrupt flag<br />
_T1IE = 1; // Enable interrupts<br />
//============================================================<br />
T1CONbits.TCS = 0; // Use internal clock source<br />
T1CONbits.TCKPS = 2; // Prescale Select 1:64<br />
T1CONbits.TON = 1; // Start the timer <br />
}<br />
//********************************************************************<br />
void _ISRFAST _T1Interrupt(void){<br />
_T1IF = 0; // Clear interrupt flag<br />
//Place user code here<br />
}<br />
<br />
====Time Measurement====<br />
*To measure the time taken for action(), use the code below:<br />
unsigned int measure_time(void){ <br />
PR3 = 0xFFFF; // Set counter to maximum<br />
_T3IF = 0; // Clear interrupt flag<br />
_T3IE = 0; // Disable interrupt<br />
T3CONbits.TON = 1; // Start the timer, TMR3 count up<br />
TMR3 = 0; //Clear TMR3 to start count up<br />
//====================================================<br />
//Add code here to wait for something to happen<br />
action();<br />
//====================================================<br />
T3CONbits.TON = 0; //Stop the timer<br />
//====================================================<br />
return (unsigned int) TMR3/FCY; //TMR/FCY yields the actual time<br />
}<br />
<br />
===Interrupt===<br />
<br />
----<br />
*Registers are involved in Interrupts includes: <br />
#Interrupt Flag Status (IFS0-IFS2) registers<br />
#Interrupt Enable Control (IEC0-IEC2) registers<br />
#Interrupt Priority Control (IPC0-IPC10) registers<br />
#Interrupt Priority Level (IPL) register<br />
#Global Interrupt Control (INTCON1, INTCON2) registers<br />
#Interrupt vector (INTTREG) register<br />
*User may assign priority level 0-7 to a specific interrupt using IPC. Setting priority to 0 disable a specific interrupt. Level 7 interrupt has the highest priority.<br />
*Current priority level is stored in bit<7:5> of Status Register (SR). Setting Interrupt Priority Level (IPL) to 7 disables all interrupts (except traps). <br />
*sti() and cli() can be defined to enable and disable global interrupts for time critical functions:<br />
#define IPL ( 0x00e0 )<br />
#define cli() SR |= IPL //Set IPL to 7<br />
#define sti() SR &= ~IPL //Set IPL to 0<br />
//============================================================<br />
char adc_ioctl(unsigned char request, unsigned char* argp){<br />
//...<br />
cli(); //Disable global interrupt<br />
for(;ch<=argp[0];ch++)<br />
adc_add_ch(argp[ch]); //Add adc channels<br />
sti(); //Enable global interrupt<br />
//...<br />
return 0;<br />
}<br />
*dsPic30F has an [http://ww1.microchip.com/downloads/en/DeviceDoc/80223D.pdf errate note] on the Interrupt Controller. When Nested Interrupt is turned on (NSTDIS=0 by default), a high priority interrupt negating a low priority interrupt may result in an Address Error.<br />
*To work around the problem, it is suggested by Microchip to use the following MACRO to protect:<br />
# the clearing of Interrput Flag<br />
# the disabling of Interrupt Enable<br />
# the lowering of Interrupt Priority <br />
# the modification of IPL in Status Register to 1-6<br />
#define DISI_PROTECT(X) { \<br />
__asm__ volatile ("DISI #0x1FFF");\<br />
X; \<br />
DISICNT = 0; \<br />
}<br />
*For example,<br />
void _ISR _T1Interrupt( void )<br />
{<br />
DISI_PROTECT(IFS0bits.T1IF = 0);<br />
//do something here...<br />
}<br />
<br />
===UART===<br />
<br />
----<br />
*5011 provides two UART channels UxART, for x=1, 2.<br />
*UxMODE, UxSTA, UxBRG are registers used to set the mode, indicate the status, and set the baud rate respectively.<br />
*For UART communications compatiable with RS232 standard, an external driver (e.g. MAX3232ESE) is needed.<br />
*For UART communications compatiable with RS485 standard, an external driver (e.g. DS3695N) is needed.<br />
====Auto baud rate detection====<br />
*The method is provided by [http://www.opencircuits.com/DsPIC30F_5011_Development_Board ingenia bootloader].<br />
*The PC sends a ASCII character 'U' (0x55) to the target board.<br />
*On the first rising edge of the start bit, the target board starts the timer.<br />
*At the fifth rising edge, the timer is stopped, let the count number be ''t_count''. <br />
**The measured period corresponds to 8 bits transmitted at a baud rate ''uxbrg''.<br />
_ _ _ _ _ _<br />
_|S|_|1|_|1|_|1|_|1|_|S|_ (S = Start Bit)<br />
<---------------><br />
Measured Time<br />
*The relationship between ''uxbrg'' and ''TMR'' is<br />
Measured Time (in seconds) = t_count/F<sub>cy</sub><br />
uxbrg = 1/(Measured Time/8)<br />
= 8*F<sub>cy</sub>/t_count<br />
*Since UxBRG is computed by:<br />
UxBRG = (F<sub>cy</sub>/(16*Baudrate)) -1<br />
= (F<sub>cy</sub>/(16*8*F<sub>cy</sub>/t_count)) -1<br />
= t_count/128 -1<br />
*The following is the code for auto baud rate detection for U2ART:<br />
unsigned int uart2_autobaud(void){<br />
U2MODEbits.ABAUD = 1; //Enable Autobaud detect from U2RX (from IC2 if 0)<br />
U2MODEbits.UARTEN = 1; //U2ART enable<br />
//Timer 3 Config==========================================================<br />
PR3 = 0xFFFF; // Set counter to maximum<br />
_T3IF = 0; // Clear interrupt flag<br />
_T3IE = 0; // Disable interrupt<br />
T3CONbits.TON = 1; // Start the timer, TMR3 count up<br />
//Input Capture Config====================================================<br />
IC2CONbits.ICM = 3; //Detect rising <br />
_IC2IF = 0; //Clear interrupt flag<br />
_IC2IE = 0; //Disable interrupt<br />
//Start Auto baud detection===============================================<br />
unsigned int i=0;<br />
cli(); //Disable Global Interrupt<br />
while(!_IC2IF); //1st rising edge detected<br />
TMR3 = 0; //Clear TMR3 to start count up<br />
_IC2IF = 0; //Clear interrupt flag<br />
while(!_IC2IF); //2nd rising edge detected<br />
_IC2IF = 0; //Clear interrupt flag<br />
while(!_IC2IF); //3rd rising edge detected<br />
_IC2IF = 0; //Clear interrupt flag<br />
while(!_IC2IF); //4th rising edge detected<br />
_IC2IF = 0; //Clear interrupt flag<br />
while(!_IC2IF); //5th rising edge detected<br />
_IC2IF = 0; //Clear interrupt flag<br />
T3CONbits.TON = 0; //Stop the timer<br />
sti(); //Enable Global Interrupt<br />
//Compute value for BRG register==========================================<br />
unsigned int time;<br />
time = ((TMR3+0x40)>>7)-1; //+0x40 for rounding<br />
//========================================================================<br />
return time;<br />
}<br />
*For 30MIP, tested speeds of transmission include 9600bps, 19200bps, 28800bps, 38400bps and 57600bps.<br />
====open()====<br />
*The following structures and variables are used as circular buffers for transmit and receive.<br />
struct UART_Rx{<br />
unsigned char wr;<br />
unsigned char rd;<br />
};<br />
struct UART_Tx{<br />
unsigned char wr; <br />
unsigned char rd;<br />
unsigned char tx_complete_flag;<br />
};<br />
struct UART_Rx uart_rx;<br />
struct UART_Tx uart_tx;<br />
unsigned char uart_rx_buf[MAX_UART_RX_BUF];<br />
unsigned char uart_tx_buf[MAX_UART_TX_BUF];<br />
<br />
char uart_open()<br />
{<br />
uart_rx.wr = 0;<br />
uart_rx.rd = 0;<br />
uart_tx.wr = 0;<br />
uart_tx.rd = 0;<br />
uart_tx.tx_complete_flag = 1;<br />
uart2_init();<br />
return 0;<br />
}<br />
<br />
void uart2_init(void){<br />
unsigned int u2brg = 97; <br />
#if(AUTO_BAUD_DECT>0)<br />
u2brg = uart2_autobaud();<br />
#endif<br />
U2BRG = u2brg; <br />
//=================================================================<br />
// Disable U2ART<br />
U2MODEbits.UARTEN = 0; //Disable U2ART module<br />
//=================================================================<br />
// Configure Interrupt Priority<br />
_U2RXIF = 0; //Clear Rx interrupt flags<br />
_U2TXIF = 0; //Clear Tx interrupt flags<br />
_U2RXIE = 1; //Receive interrupt: 0 disable, 1 enable <br />
_U2TXIE = 1; //Transmit interrupt: 0 disable, 1 enable<br />
//=================================================================<br />
// Configure Mode<br />
// +--Default: 8N1, no loopback, no wake in sleep mode, continue in idle mode<br />
// +--Diable autobaud detect<br />
// +--Enable U2ART module<br />
U2MODEbits.ABAUD = 0; //Disable Autobaud detect from U2RX <br />
U2MODEbits.UARTEN = 1; //U2ART enable<br />
//=================================================================<br />
// Configure Status<br />
// +--Default: TxInt when a char is transmitted, no break char<br />
// +--Default: RxInt when a char is received, no address detect, clear overflow<br />
// +--Enable Transmit<br />
U2STAbits.UTXEN = 1; //Tx enable<br />
}<br />
<br />
====write()====<br />
*This function writes a series of bytes to the circular buffer and start transmission.<br />
int uart_write(unsigned char *buf, int count)<br />
{<br />
//If transimt has not completed, return busy<br />
if(uart_tx.tx_complete_flag == 0){<br />
return -1; <br />
}<br />
else{<br />
uart_tx.tx_complete_flag = 0;<br />
}<br />
int next_data_pos;<br />
int byte = 0;<br />
for (; byte<count; byte++) {<br />
next_data_pos = pre_wr_cir254buf( (unsigned char)uart_tx.wr, <br />
(unsigned char)uart_tx.rd, <br />
MAX_UART_TX_BUF); <br />
if (next_data_pos!=255) {<br />
//Valid data is available<br />
uart_tx_buf[uart_tx.wr] = (unsigned char) buf[byte]; //copy the char to tx_buf<br />
uart_tx.wr = next_data_pos; //increment the ptr<br />
} else break;<br />
}<br />
//Raise Interrupt flag to initiate transmission<br />
_U2TXIF = 1; //Start interrupt<br />
return byte; <br />
}<br />
*The interrupt routine reads from the circular buffer and send the data. The uart is opened such that the module will generate an TX Interrupt when it a byte is sent.<br />
void _ISR _U2TXInterrupt(void){<br />
DISI_PROTECT(_U2TXIF = 0); //Clear Interrupt Flag<br />
unsigned char next_data_pos;<br />
next_data_pos = pre_rd_cir254buf( (unsigned char)uart_tx.wr,<br />
(unsigned char)uart_tx.rd, <br />
MAX_UART_TX_BUF);<br />
if (next_data_pos!= 255) {<br />
//Valid Data is available to transmit<br />
U2TXREG = (uart_tx_buf[(unsigned char)uart_tx.rd] & 0xFF); //send next byte...<br />
uart_tx.rd = (unsigned char) next_data_pos; //update rd pointer<br />
} else {<br />
//Transimission has completed<br />
uart_tx.tx_complete_flag = 1; // change to empty of tx<br />
}<br />
}<br />
<br />
====read()====<br />
*The interrupt routine writes to the circular buffer when space is available.<br />
void _ISR _U2RXInterrupt(void){<br />
unsigned char next_data_pos;<br />
if ( U2STAbits.URXDA ){<br />
next_data_pos = pre_wr_cir254buf( uart_rx.wr, uart_rx.rd, MAX_UART_RX_BUF);<br />
if (next_data_pos!=255) {<br />
//If buffer is not full<br />
uart_rx_buf[uart_rx.wr] = (unsigned char) U2RXREG; //Read the data from buffer<br />
uart_rx.wr = next_data_pos;<br />
} <br />
else{<br />
//When buffer is full, still remove data from register, butthe incoming data is lost<br />
next_data_pos = (unsigned char) U2RXREG; //Read the data from buffer<br />
} <br />
}<br />
DISI_PROTECT(_U2RXIF = 0); //Clear the flag<br />
}<br />
*This function reads one byte from the circular buffer.<br />
int uart_read(unsigned char *buf)<br />
{<br />
int next_data_pos;<br />
next_data_pos = pre_rd_cir254buf( uart_rx.wr, uart_rx.rd, MAX_UART_RX_BUF);<br />
//Copy 1 byte when data is available<br />
if (next_data_pos!=255) <br />
{<br />
*buf = uart_rx_buf[uart_rx.rd]; //copy the stored data to buf<br />
uart_rx.rd = next_data_pos; //update the ptr<br />
return 1;<br />
}<br />
//No data can be copied<br />
else<br />
{<br />
return 0;<br />
} <br />
}<br />
<br />
===I<sup>2</sup>C===<br />
<br />
----<br />
*Two lines are devoted for the serial communication. SCL for clock, SDA for data.<br />
*Standard communication speed includes<br />
#Standard speed mode: 100kHz<br />
#Fast speed mode: 400kHz<br />
#High speed mode: 3.4MHz<br />
*dsPIC30f5011 supports standard and fast speed modes. The maximum speed attainable is 1MHz.<br />
*Pull-up resistors are required for both SCL and SDA. Minimum pull-up resistance is given by:<br />
Pull-up resistor (min) = (V<sub>dd</sub>-0.4)/0.003 ...... [See section 21.8 in Family reference manual]<br />
*2.2Kohm is typical for standard speed mode.<br />
*After initiating a start/stop/restart bit, add a small delay (e.g. no operation) before polling the corresponding control bit (hardware controlled).<br />
*After sending a byte and receiving an acknowledgement from the slave device, ensure to change to idle state.<br />
<br />
====open()====<br />
*The following structure is used to record whether special bits are needed to be sent.<br />
typedef union{<br />
unsigned char val;<br />
struct{<br />
unsigned START:1; //start<br />
unsigned RESTART:1; //restart<br />
unsigned STOP:1; //stop<br />
unsigned NACK:1; //not acknowledgment<br />
unsigned :1;<br />
unsigned :1;<br />
unsigned :1;<br />
unsigned :1; <br />
}bits;<br />
} I2C_STATUS;<br />
static I2C_STATUS i2c_status; <br />
<br />
*Initializing I<sup>2</sup>C with default speed I2C_BRG without interrupts.<br />
void i2c_open(void)<br />
{<br />
//Open i2c if not already opened<br />
if(I2CCONbits.I2CEN == 0)<br />
{<br />
_SI2CIF = 0; //Clear Slave interrupt<br />
_MI2CIF = 0; //Clear Master interrupt<br />
_SI2CIE = 0; //Disable Slave interrupt<br />
_MI2CIE = 0; //Disable Master interrupt<br />
I2CBRG = I2C_BRG;<br />
I2CCONbits.I2CEN = 1; //Enable I2C module <br />
i2cIdle(); //I2C bus at idle state, awaiting transimission<br />
i2c_status.val = 0; //clear status flags<br />
}<br />
}<br />
<br />
====ioctl()====<br />
*Use this function before read/write to append special bits before or after the data byte.<br />
char i2c_ioctl(unsigned char request, unsigned char* argp)<br />
{<br />
switch(request){<br />
case I2C_SET_STATUS:<br />
i2c_status.val = *argp;<br />
break;<br />
default:<br />
return -1; //request code not recognised <br />
}<br />
return 0;<br />
}<br />
<br />
====write()====<br />
*This function sends an 8-bit data using the I2C protocol.<br />
Mst/Slv _______ M ____M___ S M ________ <br />
SDA (Data) |S| data |A|S|<br />
|T| |C|T|<br />
|A|XXXXXXXX|K|P|<br />
*Use ioctl() to select whether a start/restart/stop bit is required.<br />
*If slave does not respond after ACK_TIMEOUT, the transmission is considered unsucessful.<br />
int i2c_write(unsigned char *buf)<br />
{<br />
unsigned int count = 0;<br />
if(i2c_status.bits.START)<br />
{<br />
I2CCONbits.SEN = 1; <br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.SEN); //Wait till Start sequence is completed<br />
}<br />
else if(i2c_status.bits.RESTART)<br />
{<br />
I2CCONbits.RSEN = 1; <br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.RSEN); //Wait till Start sequence is completed<br />
}<br />
I2CTRN = *buf; //Transmit register<br />
while(I2CSTATbits.TBF); //Wait for transmit buffer to empty<br />
while(I2CSTATbits.ACKSTAT){<br />
if(++count > ACK_TIMEOUT){<br />
//Slave did not acknowledge, byte did not transmit sucessfully, <br />
//send stop bit to reset i2c<br />
I2CCONbits.PEN = 1;<br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.PEN); //Wait till stop sequence is completed<br />
i2cIdle();<br />
return 0;<br />
}<br />
}<br />
i2cIdle();<br />
if(i2c_status.bits.STOP)<br />
{<br />
I2CCONbits.PEN = 1;<br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.PEN); //Wait till stop sequence is completed<br />
i2cIdle();<br />
}<br />
i2c_status.val = 0; //Clear status<br />
return 1;<br />
}<br />
<br />
====read()====<br />
*This function reads 1 byte from slave using the I2C protocol.<br />
Mst/Slv ____ ___S____ M M _____ <br />
SDA (Data) | data |A|S|<br />
| |C|T|<br />
|XXXXXXXX|K|P|<br />
*Use ioctl() to select whether an ACK/NACK and/or STOP bit is needed to be sent.<br />
int i2c_read(unsigned char *buf)<br />
{<br />
I2CCONbits.RCEN = 1; //Enable Receive<br />
while(I2CCONbits.RCEN);<br />
I2CSTATbits.I2COV = 0; //Clear receive overflow<br />
*buf = (unsigned char) I2CRCV; //Access the receive buffer<br />
I2CCONbits.ACKDT = (i2c_status.bits.NACK)? 1 : 0;<br />
I2CCONbits.ACKEN = 1; //Send Acknowledgement/Not Acknowledgement<br />
i2cIdle(); //I2C bus at idle state, awaiting transimission<br />
if(i2c_status.bits.STOP)<br />
{<br />
I2CCONbits.PEN = 1;<br />
Nop(); //A small delay for hardware to respond<br />
while(I2CCONbits.PEN); //Wait till stop sequence is completed<br />
i2cIdle();<br />
}<br />
i2c_status.val = 0; //Clear status<br />
return 1;<br />
}<br />
<br />
====Example====<br />
Mst/Slv _______ M ___M___ M S ____M___ S M ___M___ M S ___S____ M ___S____ M M _____ <br />
SDA (Data) |S| | |A| |A|R| | |A| |A| |N|S|<br />
|T|address|W|C|channelA|C|E|address|R|C| Data H |C| Data L |A|T|<br />
|A|1001111|0|K|00010010|K|S|1001111|1|K|10101010|K|10XXXXXX|K|P|<br />
<br />
/*<br />
* Send start bit, slave address (Write Mode)<br />
*/ <br />
status = I2C_START;<br />
i2c_ioctl(I2C_SET_STATUS, &status);<br />
data = (unsigned char) I2C_SLAVE_ADDR;<br />
i2c_write(&data);<br />
/*<br />
* Send control byte: Channel select<br />
*/<br />
data = (unsigned char) ctrl_byte;<br />
i2c_write(&data);<br />
/*<br />
* Send restart bit, slave address (Read Mode)<br />
*/<br />
status = I2C_RESTART;<br />
i2c_ioctl(I2C_SET_STATUS, &status);<br />
data = (unsigned char) (I2C_SLAVE_ADDR|0x01);<br />
i2c_write(&data);<br />
/*<br />
* Receive High Byte with Acknowledgment<br />
*/<br />
i2c_read(&data);<br />
usr_data.high = (unsigned char) data;<br />
/*<br />
* Receive Low Byte with Not Acknowledgment and stop bit<br />
*/ <br />
status = I2C_NACK | I2C_STOP;<br />
i2c_ioctl(I2C_SET_STATUS, &status);<br />
i2c_read(&data);<br />
usr_data.low = (unsigned char) data;<br />
<br />
===ADC===<br />
<br />
----<br />
*12-bit ADC: (Max 16 Channels)<br />
*Allow a maximum of 2 sets of analog input multiplexer configurations, MUX A and MUX B (Normally use one only).<br />
*A maximum of 200kps of sampling rate when using auto sampling mode.<br />
====open()====<br />
*The following variables are required.<br />
unsigned int adc_buf[ADC_MAX_CH]; //Store most updated data<br />
volatile unsigned int* ADC16Ptr = &ADCBUF0; //Pointer to ADC register buffer, <br />
unsigned char adc_ch_select = 0; //Pointer to channel to be read from<br />
unsigned char adc_data_ready = 0; //Indicate if RAM data is ready for output<br />
*Configuration is highlighted below.<br />
**Interrupt: The ADC module will be set to interrupt when the specified channels are updated.<br />
**I/O: Set the corresponding TRISBX bits (digit i/o config) to input (i.e. = 1), and set corresponding bits in ADPCFG (analog config) to zero.<br />
**Scanning Mode: Scan mode is used. In this mode, the Sample and Hold (S/H) is switched between the channels specified by ADCSSL (Scan select register).<br />
**Reference Voltage for S/H: Only MUX A is used. By default, the negative reference voltage of the S/H is connected to V<sub>REF-</sub>.<br />
**Settings for ADC Operation: For 200kbps operation, the voltage references for the ADC voltage are connected to V<sub>REF+</sub> and V<sub>REF-</sub>. Scan input is enabled, and the module will generate an interrupt when all selected channels have been scanned.<br />
**Sampling Rate: T<sub>AD</sub> refers to the time unit for the ADC clock. To configure the ADC module at 200kbps, the minimum sampling time of 1T<sub>AD</sub> = 334ns is required. ADCS<5:0> in ADCON3 register is used to set the time, which is given by:<br />
ADCS<5:0> = 2(T<sub>AD</sub>/T<sub>CY</sub>)-1 <br />
= 2(334e-9/33.34e-9)-1 <br />
= 19<br />
<br />
char adc_open(int flags)<br />
{<br />
// Configure interrupt<br />
_ADIF = 0; //clear ADC interrupt flag<br />
_ADIE = 1; //enable adc interrupt<br />
// Configure analog i/o <br />
_TRISB0 = 1;<br />
_TRISB1 = 1; <br />
ADPCFG = 0xFFFC; //Enable AN0 (Vref+) and AN1 (Vref-)<br />
// Configure scan input channels <br />
ADCSSL = 0x0003; //0 => Skip, 1 => Scan<br />
// Configure CH0 Sample and Hold for 200kbps<br />
// +-- Use MUX A only<br />
// +-- Set CH0 S/H -ve to VRef-<br />
ADCHSbits.CH0NA = 0;<br />
// ADCCON3:<br />
// +--Auto Sample Time = 1TAD<br />
// +--A/D Conversion Clock Source = system clock<br />
// +--A/D Conversion Clock Select ADCS<5:0>= 2(TAD/TCY)-1<br />
// 200kbps(Sampling frequency)<br />
ADCON3bits.SAMC = ADC_ACQ_TIME; //1TAD for sampling time<br />
ADCON3bits.ADRC = 0; //Use system clock<br />
ADCON3bits.ADCS = ADC_ADCS; //each conversion requires 14TAD<br />
// ADCCON2:<br />
// +--Default: Use MUX A, No splitting of Buffer<br />
// +--Voltage Reference Configuration Vref+ and Vref-<br />
// +--Scan Input Selections<br />
// +--5 samples between interrupt<br />
ADCON2bits.VCFG = 3; //External Vref+, Vref-<br />
ADCON2bits.CSCNA = 1; //Scan input<br />
ADCON2bits.SMPI = 1; //take 2 samples (one sample per channel) per interrupt<br />
// ADCCON1:<br />
// +--Default: continue in idle mode, integer format<br />
// +--Enable ADC, Conversion Trigger Source Auto, Auto sampling on<br />
ADCON1bits.FORM = 0; //[0:integer]; [2 fractional]; [3 siged fractional]<br />
ADCON1bits.SSRC = 7; //auto covert, using internal clock source<br />
ADCON1bits.ASAM = 1; //auto setting of SAMP bit<br />
ADCON1bits.ADON = 1; //Turn on module<br />
return 0;<br />
}<br />
<br />
====read()====<br />
*16 registers (ADCBUF0 -ADCBUF15) are dedicated to store the ADC data between interrupts. However, the data in ADCBUFx does not necessarily correspond to the data taken for channel x. Since the lowest register will always be filled first, when some of the channels are not scanned (i.e. skipped), care must be taken. The following code checks the ADCSSL register for the current scanning channels and moves the data to the corresponding position in *adc_buf.<br />
void _ISR _ADCInterrupt(void){<br />
unsigned int channel = 0;<br />
unsigned int buffer = 0;<br />
for (; channel<ADC_MAX_CH; channel++)<br />
{<br />
if(select(channel)) //Check if channel has been selected<br />
{<br />
adc_buf[channel] = ADC16Ptr[buffer]; //Copy data to adc_buf<br />
buffer++;<br />
}<br />
}<br />
adc_data_ready = 1;<br />
DISI_PROTECT(_ADIF = 0); //Clear adc interrupt<br />
}<br />
<br />
static unsigned char select(unsigned char ch)<br />
{<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
if(ADCSSL & mask)<br />
return 1;<br />
return 0;<br />
}<br />
*User can read from the buffer at anytime to get the most updated analog values.<br />
int adc_read(unsigned int* buf, int count)<br />
{<br />
if(adc_data_ready == 1)<br />
{<br />
int num_channel = count/2; //number of channels to read<br />
unsigned char channel = adc_ch_select; //index for adc_buf<br />
int i = 0; //index for buf<br />
while(i<num_channel && channel<ADC_MAX_CH)<br />
{ <br />
//Loop only for specified number of channel or all channels <br />
buf[i++] = adc_buf[channel++]; //use data in local buffer<br />
while(select(channel)==0)<br />
{ //increment to next valid channel<br />
channel++; <br />
if(channel >= ADC_MAX_CH) break;<br />
}<br />
}<br />
return 2*i;<br />
}<br />
return -1;<br />
}<br />
<br />
====ioctl()====<br />
*This function is used to add or remove channels from the ADC scanning process.<br />
char adc_ioctl(unsigned char request, unsigned char* argp)<br />
{<br />
switch(request)<br />
{<br />
case ADC_ADD_CH:<br />
//ADD channels to current set==========================<br />
cli(); //Disable global interrupt<br />
if(select(argp[0]) == 0){ //If channel not in scan list<br />
adcAdd(argp[0]); //Add individual channel to scan list<br />
adc_data_ready = 0; //First data not ready yet, until interrupt occurs<br />
}<br />
adc_ch_select = argp[0]; //Select current channel for reading<br />
sti(); //Enable global interrupt<br />
break;<br />
case ADC_RM_CH:<br />
//REMOVE channels from current set==========================<br />
cli(); //Disable global interrupt<br />
if(select(argp[0])){ //If channel in scan list <br />
adcRm(argp[0]); //Remove individual channel<br />
adc_ch_select = 0; //Reset to AN0<br />
}<br />
sti(); //Enable global interrupt<br />
break;<br />
default:<br />
return -1; //request code not recognised <br />
}<br />
return 0;<br />
}<br />
*Channels may be added or removed by changing _TRISBX, ADPCFG, ADCSSL and ADCON2bits.SMPI.<br />
void adc_add_ch(unsigned char ch){<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
TRISB = TRISB | mask;<br />
ADCSSL = ADCSSL | mask; <br />
ADPCFG = ~ADCSSL;<br />
ADCON2bits.SMPI++; //take one more sample per interrupt<br />
}<br />
<br />
void adc_rm_ch(unsigned char ch){<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
ADPCFG = ADPCFG | mask;<br />
ADCSSL = ~ADPCFG;<br />
ADCON2bits.SMPI--; //take one less sample per interrupt<br />
}<br />
<br />
===EEPROM===<br />
<br />
----<br />
*5011 has 1024 bytes of EEPROM, readable and writable under normal voltage (5V).<br />
*To use, declare:<br />
unsigned char _EEDATA(2) eeData[1024]={ 0x00, 0x00, 0x00, 0x00, .... }<br />
unsigned int byte_pointer = 0;<br />
====lseek()====<br />
*This function moves the pointer to the desired position before a reading/writing operation is performed.<br />
int eeprom_lseek(int offset, unsigned char whence){<br />
byte_pointer = offset;<br />
return byte_pointer;<br />
}<br />
====read()====<br />
*This function read ''count'' bytes from the eeprom.<br />
int eeprom_read(unsigned char* buf, int count){<br />
int i=0;<br />
for(; i<count && byte_pointer < 1024; i++){<br />
readEEByte( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + byte_pointer, <br />
&buf[i]);<br />
byte_pointer++; //Update global pointer<br />
}<br />
return i; //read i bytes successful <br />
}<br />
*readEEByte() is implemented in assembly code as follows:<br />
.global _readEEByte<br />
_readEEByte:<br />
push TBLPAG ;w0 = base of eeData<br />
mov w0, TBLPAG ;w1 = offset for eeData in byte<br />
tblrdl.b [w1], [w2] ;w2 = pointer to user buffer<br />
pop TBLPAG<br />
return<br />
<br />
====write()====<br />
*This function write ''count'' bytes to eeprom.<br />
int eeprom_write(unsigned char* buf, int count){<br />
char isOddAddr = byte_pointer%2; //current address is odd<br />
char isOddByte = count%2; //number of bytes to write is odd<br />
//=================================================================<br />
unsigned int word_offset = byte_pointer>>1; //div by 2 and round down<br />
int max_write;<br />
max_write = (isOddAddr == 0 && isOddByte == 0) ? (count>>1) : (count>>1)+1;<br />
//=================================================================<br />
unsigned int word_data; //Store word to be written<br />
int byte_wr = 0; //number of bytes written, i.e buffer pointer<br />
int i = 0;<br />
//=================================================================<br />
for(; i<max_write && word_offset<512; i++, word_offset++){<br />
if(i==0 && isOddAddr){<br />
//First byte not used<br />
//============================================save first byte<br />
readEEByte( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + byte_pointer - 1,<br />
&word_data);<br />
//===========================================================<br />
word_data = ((unsigned int)buf[0] << 8) + (0xFF & word_data);<br />
byte_wr++; //Update buffer pointer<br />
byte_pointer++; //Update global pointer<br />
} else if(i==max_write-1 && ((isOddAddr && sOddByte==0)||(isOddAddr==0 && isOddByte))){<br />
//Last byte not used<br />
//=============================================save last byte<br />
readEEByte( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + byte_pointer + 1,<br />
&word_data);<br />
//============================================================<br />
word_data = (word_data << 8) + buf[byte_wr];<br />
byte_wr++; //Update buffer pointer<br />
byte_pointer++; //Update global pointer<br />
} else{<br />
//Both bytes valid<br />
word_data = ((unsigned int)buf[byte_wr+1] << 8) + buf[byte_wr];<br />
byte_wr+=2; //Update buffer pointer<br />
byte_pointer+=2; //Update global pointer<br />
}<br />
//==================================================================<br />
eraseEEWord( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + 2*word_offset);<br />
writeEEWord( __builtin_tblpage(eeData), <br />
__builtin_tbloffset(eeData) + 2*word_offset,<br />
&word_data);<br />
//==================================================================<br />
}<br />
return byte_wr; //No. of byte written<br />
}<br />
*eraseEEWord and writeEEWord are implemented in assembly.<br />
.global _eraseEEWord<br />
_eraseEEWord:<br />
push TBLPAG <br />
mov w0, NVMADRU ;w0 = base of eeData<br />
mov w1, NVMADR ;w1 = offset for eeData in word<br />
mov #0x4044, w0 <br />
mov w0, NVMCON ;Set to erase operation<br />
push SR ;Disable global interrupts<br />
mov #0x00E0, w0<br />
ior SR<br />
mov #0x55, w0 ;Write the KEY sequence<br />
mov w0, NVMKEY<br />
mov #0xAA, w0 <br />
mov w0, NVMKEY<br />
bset NVMCON, #15 ;Start the erase cycle, bit 15 = WR<br />
nop<br />
nop<br />
L1: btsc NVMCON, #15 ;while(NVMCONbits.WR)<br />
bra L1<br />
clr w0<br />
pop SR ;Enable global interrupts<br />
pop TBLPAG<br />
return<br />
<br />
.global _writeEEWord<br />
_writeEEWord:<br />
push TBLPAG ;w0 = base of eeData<br />
mov w0, TBLPAG ;w1 = offset for eeData in byte<br />
tblwtl [w2], [w1] ;w2 = pointer to user buffer<br />
mov #0x4004, w0 ;Set to write operation<br />
MOV w0, NVMCON<br />
push SR ;Disable global interrupts<br />
mov #0x00E0, w0<br />
ior SR<br />
mov #0x55, w0 ;Write the KEY sequence<br />
mov w0, NVMKEY<br />
mov #0xAA, w0 <br />
mov w0, NVMKEY<br />
bset NVMCON, #15 ;Start the erase cycle, bit 15 = WR<br />
nop<br />
nop<br />
L2: btsc NVMCON, #15 ;while(NVMCONbits.WR)<br />
bra L2<br />
clr w0<br />
pop SR ;Enable global interrupts<br />
pop TBLPAG<br />
return<br />
<br />
===Simple PWM (Output Compare Module)===<br />
<br />
----<br />
<br />
*The PWM module consists of 8 channels using the output compare module of dsPic.<br />
*These channels are locate at pin 46 (OC1), 49 (OC2), 50 (OC3), 51 (OC4), 52 (OC5), 53 (OC6), 54 (OC7), 55 (OC8). These pins are shared with port D.<br />
*The range of PWM freqeuencies obtainable is 2Hz to 15MHz (See Figure 6.3). Suggested range of operation is 2Hz to 120kHz. The relationship between resolution ''r'' and PWM frequency ''f''<sub>PWM</sub> is given by:<br />
f<sub>PWM</sub> = f<sub>CY</sub>/(Prescale*10<sup>rlog(2)</sup>)<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 6.3 Relationship of Resolution and PWM Frequency<br />
! Resolution (bit) !! Prescale=1 !! Prescale=8 !! Prescale=64 !! Prescale=256<br />
|- <br />
|1||15,000,000 ||1,875,000 ||234,375||58,594 <br />
|- <br />
|2||7,500,000 ||937,500 ||117,188 ||29,297 <br />
|- <br />
|3||3,750,000 ||468,750 ||58,594 ||14,648 <br />
|- <br />
|4||1,875,000 ||234,375 ||29,297 ||7,324 <br />
|- <br />
|5||937,500 ||117,188 ||14,648 ||3,662 <br />
|- <br />
|6||468,750 ||58,594 ||7,324 ||1,831 <br />
|- <br />
|7||234,375 ||29,297 ||3,662 ||916 <br />
|- <br />
|8||117,188 ||14,648 ||1,831||458 <br />
|- <br />
|9||58,594 ||7,324 ||916 ||229 <br />
|- <br />
|10||29,297 ||3,662 ||458 ||114 <br />
|- <br />
|11||14,648 ||1,831 ||229||57 <br />
|- <br />
|12||7,324 ||916 ||114 ||29 <br />
|- <br />
|13||3,662 ||458 ||57 ||14 <br />
|- <br />
|14||1,831 ||229 ||29 ||7 <br />
|- <br />
|15||916 ||114 ||14 ||4 <br />
|- <br />
|16||458 ||57 ||7 ||2 <br />
|-<br />
|}<br />
<br />
====open()====<br />
*A timer (either Timer 2 or 3) is needed to determine the pwm period. The following code uses timer 2 for all 8 channels.<br />
void pwm_open(void){<br />
OC1CON = 0; OC2CON = 0; //Disable all output compare modules<br />
OC3CON = 0; OC4CON = 0;<br />
OC5CON = 0; OC6CON = 0;<br />
OC7CON = 0; OC8CON = 0;<br />
//============================================================<br />
TMR2 = 0; // Clear register<br />
PR2 = 0xFFFF; // Set to Maximum<br />
//============================================================<br />
_T2IF = 0; // Clear interrupt flag<br />
_T2IE = 0 // Enable interrupts<br />
//============================================================<br />
T2CONbits.TCS = 0; // Use internal clock source<br />
T2CONbits.TCKPS = 0; // Prescale Select 1:1<br />
//============================================================<br />
T2CONbits.TON = 1; // Start the timer <br />
}<br />
<br />
====ioctl()====<br />
*User should select the channel and set the pwm period using the functions below before issuing the duty cycle:<br />
char pwm_ioctl(unsigned char request, unsigned long* argp){<br />
unsigned int value;<br />
unsigned char mask;<br />
switch(request){<br />
case PWM_SET_PERIOD:<br />
return setPeriodNPrescale(argp[0]);<br />
case PWM_SELECT_CH:<br />
pwm_channel = argp[0];<br />
mask = 0x01 << pwm_channel;<br />
pwm_status = pwm_status | mask;<br />
return 0;<br />
default:<br />
return -1;<br />
}<br />
}<br />
char setPeriodNPrescale(unsigned long value_ns){<br />
unsigned long ans;<br />
unsigned long long numerator = (unsigned long long)value_ns*SYSTEM_FREQ_MHZ;<br />
int index= -1;<br />
unsigned long denominator;<br />
//-------------------------------------------------<br />
do{<br />
denominator = (unsigned long)1000*pwm_prescale[++index];<br />
ans = (unsigned long)(((long double)numerator/denominator) + 0.5) - 1; //round to nearest int<br />
} while(ans > 0x0000FFFF && index < 3);<br />
//-------------------------------------------------<br />
if(ans > 0x0000FFFF)<br />
return -1;<br />
//-------------------------------------------------<br />
T2CONbits.TON = 0; // Turn off the timer<br />
T2CONbits.TCKPS = index; // Change prescale factor<br />
PR2 = (unsigned int) ans; // Set to Maximum<br />
T2CONbits.TON = 1; // Turn on the timer <br />
//-------------------------------------------------<br />
return 0;<br />
}<br />
<br />
====write()====<br />
*User can change the duty cycle using the following functions<br />
int pwm_write(unsigned long* buf){<br />
if((pwm_status & (0x01 << pwm_channel)) == 0){<br />
return -1; //Channel has not been enabled<br />
}<br />
switch(pwm_channel){<br />
case 0:<br />
OC1RS = calcDCycle(buf[0]); OC1R = OC1RS; <br />
OC1CONbits.OCM = 6; //Simple PWM, Fault pin disabled<br />
break;<br />
case 1:<br />
OC2RS = calcDCycle(buf[0]); OC2R = OC2RS; <br />
OC2CONbits.OCM = 6; //Simple PWM, Fault pin disabled<br />
break;<br />
...<br />
case 7:<br />
OC8RS = calcDCycle(buf[0]); OC8R = OC8RS; <br />
OC8CONbits.OCM = 6; //Simple PWM, Fault pin disabled<br />
break; <br />
default:<br />
return -1;<br />
}<br />
return 4;<br />
}<br />
unsigned int calcDCycle(unsigned long value_ns){<br />
unsigned long long numerator = (unsigned long long)value_ns*SYSTEM_FREQ_MHZ;<br />
unsigned int index = T2CONbits.TCKPS;<br />
unsigned long denominator = (unsigned long)1000*pwm_prescale[index];<br />
return (unsigned int)(((long double)numerator/denominator) + 0.5) - 1; //round to nearest int<br />
}<br />
<br />
====Propagration Delay====<br />
*PWM channels sharing the same timer will have their PWM signals synchronised (i.e. the HIGH state of the duty cycle are all triggered together).<br />
*To introduced delay to the PWM signals, the signal from selected channels may be made to pass through a series of inverters (e.g. 74HC14D). This adds propagation delay to the signal.<br />
*However, as propagration delay of logic gates depends on applied voltage, temperature and load capacitance, the accuracy is low and performance is poor. For accurate delay, delay lines may be used, but they are expensive.<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 6.4 Propagation Delay of [http://www.nxp.com/acrobat_download/datasheets/74HC_HCT14_3.pdf Philips 74HC14D]<sup>[1], [2]</sup><br />
! !! 3.3V !! !! !! 5.0V !! !!<br />
|- <br />
! Number of Gates !! A !! B !! C !! A !! B !! C<br />
|- <br />
| 2 <br />
| 21ns (10.5)|| 23ns (11.5)|| 22ns (11.0)<br />
| 15ns (7.5)|| 14ns (7.0)|| 14ns (7.0)<br />
|-<br />
| 4 <br />
| 45ns (11.3)|| 46ns (11.5)|| 46ns (11.5) <br />
| 30ns (7.5)|| 30ns (7.5)|| 30ns (7.5)<br />
|-<br />
| 6 <br />
| 69ns (11.5)|| 70ns (11.7)|| 72ns (12.0) <br />
| 45ns (7.5)|| 46ns (7.7)|| 47ns (7.8)<br />
|- <br />
|}<br />
[1] Data in specification for 4.5V: Typical 15ns, Maximum 25ns<br><br />
[2] Data in specification for 6.0V: Typical 12ns, Maximum 21ns<br />
<br />
===DSP Library===<br />
<br />
----<br />
*Library functions in <dsp.h> include the following categories: <br />
#Vector<br />
#Window<br />
#Matrix<br />
#Filtering<br />
#Transform<br />
#Control<br />
<br />
====Data Types====<br />
*Signed Fractional Value (1.15 data format)<br />
**Inputs and outputs of the dsp functions adopt 1.15 data format, which consumes 16 bits to represent values between -1 to 1-2<sup>-15</sup> inclusive.<br />
**Bit<15> is a signed bit, positive = 0, negative = 1.<br />
**Bit<14:0> are the exponent bits ''e''.<br />
**Positive value = 1 - 2<sup>-15</sup>*(32768 - ''e'')<br />
**Negative value = 0 - 2<sup>-15</sup>*(32768 - ''e'')<br />
*40-bit Accumulator operations (9.31 data format)<br />
**The dsp functions use the 40 bits accumalators during arithmatic calculations.<br />
**Bit<39:31> are signed bits, positive = 0x000, negative = 0x1FF.<br />
**Bit<30:0> are exponent bits.<br />
*IEEE Floating Point Values<br />
**Fractional values can be converted to Floating point values using: '''fo = Fract2Float(fr);''' for fr = [-1, 1-2<sup>-15</sup>]<br />
**Floating point values can be converted to Fractional values using: '''fr = Float2Fract(fo);''' or '''fr = Q15(fo);''' for fo = [-1, 1-2<sup>-15</sup>]<br />
**Float2Fract() is same as Q15(), except having saturation control. When +ve >= 1, answer = 2<sup>15</sup>-1 = 32767 (0x7FFF). When -ve < -1, answer = -2<sup>15</sup> = -32767 (0x8000)<br />
<br />
===Build-in Library===<br />
<br />
----<br />
*Some assembler operators can only be accessed by inline assembly code, for example, <br />
#Manuipulation of accumulators A and B (add, sub, mul, divide, shift, clear, square)<br />
#Bit toggling<br />
#Access to psv (program space visiblity) page and offset<br />
#Access to table instruction page and offset<br />
*Built-in functions are written as C-like function calls to utilize these assembler operators.<br />
<br />
<br />
==Bootloader Development==<br />
<br />
===Concepts===<br />
*Programming with ICSP is useful when the target board is produced in batch. The producer can download a program even when the chip is on the target board.<br />
*However, ICSP requires an external programmer.<br />
*To allow the user to change the program after production but without the need of an external programmer, bootloader becomes useful.<br />
*Bootloader is a small program installed via ICSP. Everytime the device is reset, the bootloader is run first. The bootloader first detects the default serial channel whether the user wishes to download a new program to the device. If so, the bootloader will pause there, and wait for the user to download the hex file from the PC. The hex file is written to the device via RTSP instructions in the bootloader. If a new download is not necessary, the bootloader redirects to the previously installed user's program.<br />
*The disadvantage of bootloaders is that they consume some of the memory of the device.<br />
<br />
<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 7.1 Free bootloaders for dsPIC<br />
! Developer<br />
! Source<br />
! Platform<br />
! User Guide<br />
! Remarks<br />
|- valign="top"<br />
| [http://www.ingenia-cat.com/index.php?lang=en ingenia]<br />
| [http://www.ingenia-cat.com/download/iBL.s Assembly]<br />
| [http://www.ingenia-cat.com/download/ingeniadsPICbootloader1.1.zip Windows]<br />
| [http://www.ingenia-cat.com/reference/pdf/iBL.UG.V1.2.pdf pdf]<br />
| <br />
*Works for all dsPIC supporting RTSP<br />
*Auto baudrate detection<br />
*Use about 1.15% of the flash memory space (0xAFFF-0xAE00)/(0xAFFF-0x0100)<br />
*Development of Linux platform is underway<br />
*Modification of code for dsPIC30F5011 is successful<br />
|-valign="top"<br />
| [http://www.etc.ugal.ro/cchiculita/software/picbootloader.htm Tiny]<br />
| [http://www.etc.ugal.ro/cchiculita/software/tinybld191.zip Assembly]<br />
| Windows<br />
| [http://www.etc.ugal.ro/cchiculita/software/tinybldusage.htm Web]<br />
| <br />
*By default, only supports 601X, 601X, 401X, 2010<br />
*Smaller code size than ingenia, but not as easy to modify<br />
|-valign="top"<br />
| [http://www.via.si/software/dsPIC_bootloader/ Elektronika]<br />
| [http://www.via.si/software/dsPIC_bootloader/data/ Hex]<br />
| Windows<br />
| [http://www.via.si/software/dsPIC_bootloader/data/README.txt txt]<br />
| <br />
*Only works for dsPIC30F6014 serial port UART2 at baudrate 57600<br />
|-<br />
|}<br />
<br />
===dsPicBootloader===<br />
<br />
*The bootloader developed by ingenia is open source and it has been modified (see below) to suit our development using dsPic30f5011.<br />
*The bootloader (hereafter called dsPicBootloader) employs the following settings:<br />
# Use U2ART channel<br />
# Use FRC, PLL16<br />
# For 5011, the bootloader is located between 0x00AE00 to 0x00AFFE (512bytes). Refer to C:\Program Files\Ingenia\ingeniadsPICbootloader\ibl_dspiclist.xml after installing the GUI interface.<br />
*Changes made to [http://www.ingenia-cat.com/download/iBL.s assembly code] includes:<br />
1. including p30f5011.gld and p30f5011.inc<br />
.include "p30f5011.inc"<br />
2. changing the config code of UART #0x8420 -> #0x8020<br />
; Uart init<br />
mov '''#0x8020''', W0 ; W0 = 0x8020 -> 1000 0000 0010 0000b<br />
mov W0, U2MODE ; Enable UART, AutoBaud and 8N1<br />
clr U2STA<br />
3. changing the start address 0xAE00 - 0x0100 = 0AD00<br />
.equ CRC, W4<br />
.equ ACK, 0x55<br />
.equ NACK, 0xFF<br />
.equ USER_ADDRESS, 0x0100<br />
.equ START_ADDRESS, '''0xAD00''' ; Relative to 0x0100<br />
4. using Internal FRC and PLL16<br />
config __FOSC, CSW_FSCM_OFF & '''FRC_PLL16''' ;Turn off clock switching and<br />
;fail-safe clock monitoring and<br />
;use the Internal Clock as the<br />
;system clock<br />
5. disabling MCLR (optional)<br />
config __FBORPOR, PBOR_ON & BORV_27 & PWRT_16 & '''MCLR_DIS'''<br />
;Set Brown-out Reset voltage and<br />
;and set Power-up Timer to 16msecs<br />
6. changing all the related registers of U1ART to U2ART, all U1XXX => U2XXX<br />
'''U2MODE, U2STA, U2BRG, U2RXREG, U2TXREG'''<br />
7. changing all the related registers of IC1 to IC2, all IC1XXX => IC2XXX<br />
'''IC2CON, #IC2IF, #IC2IE'''<br />
<br />
===dsPicProgrammer (Java-based Multi-Platformed)===<br />
*Ingenia developed a programmer (PC-side) that works only in Windows environment. The project for Linux environment is currently suspended.<br />
*A simple programmer (hereafter called dsPicProgrammer) written in Java based on the library developed by [http://www.rxtx.org/ RXTX] has been developed here. The programmer supports both Linux and Windows environments, and may be used as a substitution for the official programmer developed by ingenia.<br />
*The programmer has the following specification and limitations:<br />
#Can be used on both Linux and Windows platforms.<br />
#Adjustable baudrate (9600bps to 57600bps).<br />
#Support programming of dsPIC30F5011 and dsPIC33FJ128GP306 devices (Developers may add your devices).<br />
#Protection against overwriting bootloader codes on devices.<br />
#Detection if application program does not have its reset() at user's code start address.<br />
#Reprogramming can be done without powering down the target board, provided the user's program is compliant to that stated below.<br />
#Target board will run the user's program after programming is done.<br />
#Can be used with USB-Serial Cables. Below is a list of tested cable:<br />
::[http://www.prolific.com.tw/eng/Products.asp?ID=59 Prolific PL-2303 USB to Serial Bridge Controller]: [http://www.prolific.com.tw/eng/downloads.asp?ID=31 Driver download]<br />
<br />
===Special Consideration===<br />
*The bootloader assumes that the user program starts at address 0x100. This is usually the case, but there are always exceptions.<br />
*To ensure that the user program always starts at address 0x100, you can create a customized linker script and customized reset() function as follows:<br />
:*Copy and modify the file named "crt0.s" from the directory "C:\Program Files\Microchip\MPLAB C30\src\pic30" to the project directory and include it.<br />
.section .reset, code //previously .section .libc, code <br />
:*Copy and modify the linkerscript for the device (e.g. p30f5011.gld) to the project directory and include it.<br />
.text __CODE_BASE :<br />
{<br />
*(.reset); //<-insert this line here<br />
*(.handle);<br />
*(.libc) *(.libm) *(.libdsp); /* keep together in this order */<br />
*(.lib*);<br />
*(.text);<br />
} >program<br />
<br />
===Communication Protocol===<br />
<br />
+-------------------+ +-------------------+----------------+<br />
| dsPicProgrammer | | dsPicBootloader | User's Program |<br />
+-------------------+ +-------------------+----------------+<br />
| PC | | Target dsPic |<br />
+-------------------+ +------------------------------------+<br />
| COM PORT |=============| UART |<br />
+-------------------+ +------------------------------------+<br />
<br />
* '''Stage 1: User's Configuation'''<br />
**Select a COM port channel<br />
**Select a baudrate<br />
**Select the user hex file<br />
java -jar dsPicProgrammer.jar COM1 19200 foo.hex<br />
* '''Stage 2: Resetting Target Device'''<br />
**dsPicProgrammer sends a Break character (pull UART-TX to low logic, which is normally high).<br />
**User's program on dsPic detects the break character and reset the chip<br />
::NOTE: The user's program is expected to have the following code in order to enable this function. Otherwise, the target board must be restarted manually.<br />
void _ISR _U2RXInterrupt(void)<br />
{<br />
//No Framming error<br />
if( U2STAbits.FERR == 0)<br />
{<br />
//Normal procedure<br />
}<br />
//Framming error<br />
else<br />
{<br />
if ( U2STAbits.URXDA ){<br />
unsigned char data;<br />
data = (unsigned char) U2RXREG;<br />
if(data == 0x00){<br />
// A break char has been received: <br />
// U2RX has been pulled to zero for more than 13 bits<br />
// This is used to reboot the pic<br />
mdelay(800); //wait for break character to clear<br />
asm("reset"); //software reset<br />
}<br />
} <br />
}<br />
_U2RXIF = 0; //Clear the flag<br />
}<br />
* '''Stage 3: Entering Ingenia's Protocol'''<br />
** Transmission is conducted in 8N1, i.e. 8-bit, no parity, 1 stop-bit<br />
** Communication Protocol is reviewed in [http://www.ingenia-cat.com/reference/pdf/iBL.UG.V1.2.pdf ingenia bootloader user's guide] section 2.1.3. The following summarises the key steps on the PC side (Refer also to section 2.2.2).<br />
::#Autobaud rate detection: dsPicProgrammer continuously sends a character "U" [0x55] via COM port and waits for an acknowledgment character "U", [ACK] = [0x55]<br />
::#Version Control: dsPicProgrammer sends the command character [0x03]. On success, dsPicProgrammer receives 3 characters i) Major Version ii) Minor Version iii) Acknowledgment [0x55]<br />
::#Device ID Monitoring: dsPicProgrammer sends the read command character [0x01] + 24-bit address [High][Medium][Low] (0xFF0000). Then, it receives 4-byte data [High][Medium][Low][ACK]<br />
::#Load the user hex file and check integrity<br />
::#Start Programming: dsPicProgrammer issues the write command character [0x02] + 24-bit address [High][Medium][Low]+ Number of bytes [N] + [data 0] + [data 1] + ... + [data N-1] + [CRC]=(INTEL HEX8 Checksum - Sum modulo 256) and receives [ACK] or [NACK] = [0xFF]<br />
::NOTE: Writing is in row mode access (i.e. erase and write a whole row, each row has 32 instructions, or 96 bytes because each instruction has 24 bits)<br />
* '''Stage 4: Goto User's Program'''<br />
**dsPicProgrammer sends the goto user code command [0x0F]<br />
<br />
<br />
==USB-RS232 Bridge==<br />
<br />
*As USB ports are becoming more and more common, COM ports and Parallel ports may be redundant in the next few years. This section explore the possibilities of programming the target board through a USB port.<br />
*There are two options:<br />
#Use an external USB/RS232 adaptor, the driver will emulate a virtual COM port, such as [http://www.prolific.com.tw/eng/downloads.asp?ID=31 Prolific] and [http://www.ftdichip.com/Drivers/VCP.htm FDTI]. Ingenia has tested its bootloader with some USB-232 manufacturers (silabs, FTDI, etc..). However, the programming failed with our Prolific adapter. Application program may use [http://java.sun.com/products/javacomm/ JavaComm API] (javax.comm) and/or [http://www.rxtx.org/ RXTX] to drive the COM port.<br />
#Modified the bootloader program on PC to support USB communication. e.g. using [http://jusb.sourceforge.net/ jUSB] and [http://javax-usb.org/ JSR-80] (javax.usb). External circuits such as PIC18F4550 and MAX232 are required.<br />
<br />
|--User's App.--|-------Device Manager------|-------USB-RS232 Interface------|---dsPIC---|<br />
Option 1:<br />
+-------------+ +----------+ +----------+ +---+ +------------+ +-----+ +--------+<br />
| Application |--| JavaComm |--| Virtual |==|USB|--| FDTI |--|RS232|==| Target |<br />
| Program | | RXTX | | COM Port | +---+ | Circuitary | +-----+ | Board |<br />
+-------------+ +----------+ +----------+ +------------+ +--------+<br />
Option 2:<br />
+-------------+ +--------+ +---+ +------------+ +-----+ +--------+<br />
| Application |----------| JSR-80 |==========|USB|--| PIC18F4550 |--|RS232|==| Target |<br />
| Program | | jUSB | +---+ | MAX232 | +-----+ | Board |<br />
+-------------+ +--------+ +------------+ +--------+<br />
<br />
*Currently, when RXTX is incorporated with JavaComm API, operating systems supported include Linux, Windows, Mac OS, Solaris and other operating systems. On the other hand, jUSB and JSR-80 only works for linux.<br />
<br />
===FDTI Chipset===<br />
*FT232RL communicates with PC via USB to provide 1 UART channel.<br />
*Datasheet can be downloaded [http://www.ftdichip.com/Documents/DataSheets/DS_FT232R.pdf here]. <br />
**Refer to Fig. 11 (Page 19) for Bus Powered Configuration.<br />
**Refer to Fig. 16 (Page 24) for for UART TTL-level Receive [RXD -> 1], Transmit [TXD -> 4], Transmit Enable [CBUS2/TXDEN -> 3]. Omit Receive Enable [CBUS3/PWREN#] and use [CBUS2/TXDEN -> 2] <br />
**Refer to Fig. 15 (Page 23) for LED Configuration: [CBUS0/TXLED#] and [CBUS1/RXLED#]<br />
*Virtual COM Port Drivers can be downloaded [http://www.ftdichip.com/Drivers/VCP.htm here].<br />
<br />
<br />
==Programming the Device==<br />
<br />
===Requirements===<br />
*Hardware<br />
#PC with COM port (Windows XP Installed for MPLAB)<br />
#ICD2 Programmer<br />
#Target Board<br />
#5V Power Supply<br />
<br />
*Software<br />
#[http://ww1.microchip.com/downloads/en/DeviceDoc/MP750.zip MPLAB IDE v7.50]: v7.60 is not compatible with our current [http://www.sure-electronics.com/ ICD2 Programmers]. There are consistent "Devices cannot be founded" warnings.<br />
#[http://chungyan5.no-ip.org/websvn/listing.php dsPicProgrammer] ('''dsPicProgrammer.jar''')<br />
#[http://users.frii.com/jarvi/rxtx/download.html RXTX driver]: download and upzip rxtx-2.1-7-bins-r2.zip (Final)<br />
<br />
*Files<br />
#[http://chungyan5.no-ip.org/websvn/listing.php dsPicBootloader] ('''bl_5011.hex'''). Original assembly code by ingenia can be downloaded from [http://www.ingenia-cat.com/download/iBL.s here].<br />
#Application hex file (e.g. '''app.hex''')<br />
<br />
===Loading Bootloader (Once only)===<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 9.1 Loading Bootloader<br />
! Step !! Remarks <br />
|-valign="top"<br />
| Install [http://ww1.microchip.com/downloads/en/DeviceDoc/MP750.zip MPLAB IDE] || <br />
*Do '''NOT''' connect ICD 2 (via USB) to PC<br />
*Execute '''MPLAB vX.XX Install.exe'''<br />
|-valign="top"<br />
| Install USB Driver ||<br />
*Follow the instruction in (C:\Program Files\Microchip\MPLAB IDE\ICD2\Drivers\Ddicd2.htm)<br />
|-valign="top"<br />
| Select Target Chip ||<br />
*Run MPLAB IDE on PC<br />
*Select: Configure>Select Devices...<br />
*Choose dsPIC30F5011<br />
|-valign="top"<br />
| Target <-> ICD 2 ||<br />
*Use six pin cable. Beware of the pin assignments. Only pin 1 - 5 should be used.<br />
*Place Jumper on target board (if any). The Jumper connects target V<sub>cc</sub> to ICD 2.<br />
*Do '''NOT''' power-up the target.<br />
|-valign="top"<br />
| ICD 2 <-> PC ||<br />
*Plug-in ICD 2 to PC via USB cable<br />
*Power-up the target.<br />
*Select: Programmer>Select Programmer>MPLAB ICD 2<br />
*If this is the first time the ICD 2 is connected to PC, MPLAB IDE will automatically download the required OS to ICD 2, wait until it has finished<br />
*If you have not connected and powered up the target, you might see Warnings on invalid device IDs, and/or running self tests.<br />
*See results of self test if necessary: Programmer>Settings, Status Tab. Refer to [http://ww1.microchip.com/downloads/en/DeviceDoc/51331B.pdf ICD2 User's Guide] Chapter 7.<br />
|-valign="top"<br />
| Load Bootloader ||<br />
*Select: File>Import...<br />
*Select '''bl_5011.hex'''<br />
|-valign="top"<br />
| Start Programming ||<br />
*Select: Programmer>Program<br />
|-valign="top"<br />
| Finishing ||<br />
*Power-down the Taget<br />
*Select: Programmer>Select Programmer>None<br />
*Unplug USB cable<br />
|-<br />
|}<br />
<br />
===Loading Firmware===<br />
====Java Environment Setup====<br />
*Download and install the latest JDK or JRE<br />
**Available from [http://java.sun.com/javase/downloads/index.jsp Sun Microsystems] (e.g. JDK 6 Update 3)<br>[[Image:1 1 java.JPG]]<br><br />
*Download and Extract RXTX Driver <br />
**Available from [http://users.frii.com/jarvi/rxtx/download.html RXTX] <br />
**File: rxtx-2.1-7-bins-r2.zip (Final)<br />
**Extract the files using software such as WinRAR<br>[[Image:1 2 rxtx.JPG]]<br><br />
*Copy RXTXcomm.jar<br />
**To C:\Program Files\Java\X\lib\ext (under the latest jre, e.g. X = jre1.6.0_03)<br>[[Image:1 3 rxtxcomm.JPG]]<br><br />
*Copy rxtxSerial.dll<br />
**To C:\Program Files\Java\X\bin (under the lastest jre, e.g. X = jre1.6.0_03)<br />
**For Linux users, copy librxtxSerial.so to /jre/lib/[machine type] (i386 for instance)<br>[[Image:1 4 rxtxserial.JPG]]<br><br />
*Download dsPicProgrammer <br />
**Available from http://chungyan5.no-ip.org/websvn/listing.php <br />
**Expand the latest tag under dsPicProgrammer<br />
**File: dsPicProgrammer.jar<br>[[Image:1 5 dspicprogrammer.JPG]]<br><br />
**Save the file (dsPicProgrammer.jar) and your hex file (foo.hex) to your local directory (e.g. C:\dsPicProgrammer\)<br>[[Image:1 6 dspicprogrammer2.JPG]]<br><br />
====Download Firmware====<br />
*Start a Command Prompt<br />
**Start -> Run<br>[[Image:2 1 run.JPG]]<br><br />
**Enter cmd<br>[[Image:2 2 cmd.JPG]]<br><br />
*Run dsPicProgrammer<br />
**Change to the directory where dsPicProgrammer.jar is located and run the command:<br>java -jar dsPicProgrammer.jar COM1 57600 foo.hex (Windows)<br>java -jar dsPicProgrammer.jar /dev/ttyS0 57600 foo.hex (Linux)<br>where COM1 is your COM Port ID<br>57600 is communication speed [in bps]<br>foo.hex is your firmware new file<br>[[Image:2 3 command.JPG]]<br><br />
**When the program prompt you for an input, press y:<br>[[Image:2 4 prompt.JPG]]<br><br />
**If communication can be established, you should see something like this:<br>[[Image:2 5 progress.JPG]]<br><br />
**Wait until programming is completed.<br>[[Image:2 6 complete.JPG]]<br><br />
====Troubleshooting====<br />
*Invalid COM Port<br />
**In case of selecting an invalid COM port, you should see the error message:<br>gnu.io.NoSuchPortException: Choosing COM Port Error<br>[[Image:3 1 com err.JPG]]<br><br />
*Missing firmware file<br />
**In case of selecting a firmware file that does not exist, you should see the error message:<br>java.io.FileNotFoundException: foo1.hex <The system cannot find the file specified><br>[[Image:3 2 file err.JPG]]<br><br />
*Missing RXTX driver<br />
**In case of missing the RXTX driver, you should see the error message:<br>Exception in thread “main” java.lang.NoClassDefFoundError: gnu/io/UnsupportedCommOperationException<br>[[Image:3 3 rxtx err.JPG]]<br><br />
<br />
<br />
==Remote Access==<br />
*At the moment, local devices (e.g. EEPROM, ADC, DAC, etc.) can only be accessed locally through POSIX functions such as open(), read(), write(), ioctl().<br />
*However, a client may need to access these devices on a remote server. This section reviews the background and gives some ideas on its possible implementation.<br />
<br />
===Requirements===<br />
*A remote file access protocol, to transfer "files" (i.e. device's data) such as:<br />
#[http://en.wikipedia.org/wiki/FTP File Transfer Protocol] (FTP): Required files are copied from sever to client for manipulation<br />
#[http://en.wikipedia.org/wiki/Remote_Shell Remote Shell] (RSH): Required files are copied from sever to client for manipulation<br />
#[http://en.wikipedia.org/wiki/Network_File_System_%28Sun%29 Network File System] (NFS): Required files are manipulated on sever<br />
*An API to access files using a selected protocol, such as:<br />
#[http://www.die.net/doc/linux/man/man2/lam_rfposix.2.html lam_rfposix]: A POSIX-like remote file service for Local Area Multicomputer<br />
#API employed by VxWorks: [http://en.wikipedia.org/wiki/VxWorks VxWorks] is a Unix-like real-time operating system, commonly used for embedded systems.<br />
<br />
===API Reference for VxWorks===<br />
*Reference:<br />
**[http://www.windriver.com/vxworks/ VxWorks Official Website]<br />
**[http://www-cdfonline.fnal.gov/daq/commercial/ OS Libraries API Reference]<br />
*Related Libraies<br />
**netDrv (netDrv.h): an API using FTP or RSH<br />
**nfsDrv (nfsDrv.h): an API using NFS<br />
<br />
<br />
==Conversion to dsPIC33F Devices==<br />
*This section discusses the conversion required from dsPIC30F5011 to dsPIC33FJ128GP306.<br />
*Refer to official document [http://ww1.microchip.com/downloads/en/DeviceDoc/70172A.pdf dsPIC30F to dsPIC33F Conversion Guidelines] (DS70172A).<br />
*Note that this section does not mainly intend to introduce the new functionalities of dsPIC33F devices. It only serves the purpose to summarise the major (if not minimum) changes required to port the setup of dsPIC30 to dsPIC33 devices.<br />
<br />
===Hardware===<br />
*dsPIC33 operates at voltage of 3.3V. A voltage regulator, such as [http://www.national.com/ds.cgi/LM/LM3940.pdf LM3940] can be used to convert 5V supply to 3.3V.<br />
*A 1uF capacitor has to be placed at pin 56 (previously V<sub>SS</sub>, now V<sub>DDCORE</sub>).<br />
<br />
===Software===<br />
<br />
====Configuration Bits====<br />
<br />
----<br />
*dsPIC33 can operate at 40MIPs at maximum. To configure the device using internal FRC, replace the configuration bits setting as follows:<br />
_FOSCSEL(FNOSC_FRCPLL); // FRC Oscillator with PLL<br />
_FOSC(FCKSM_CSDCMD & OSCIOFNC_ON & POSCMD_NONE); <br />
// Clock Switching and Fail Safe Clock Monitor is disabled<br />
// OSC2 Pin Function: OSC2(RC15) as Digital IO<br />
// Primary Oscillator Mode: Disabled<br />
_FWDT(FWDTEN_OFF); // Watchdog Timer Enabled/disabled by user software <br />
*Configure on-chip PLL at runtime as follows (at start of main function):<br />
_PLLDIV = 38; // M=40: PLL Feedback Divisor bits<br />
CLKDIV = 0; // N1=2: PLL VCO Output Divider Select bits<br />
// N2=2: PLL Phase Detector Input Divider bits<br />
OSCTUN = 22; // Tune FRC oscillator, if FRC is used; <br />
// 0: Center frequency (7.37 MHz nominal)<br />
// 22: +8.25% (7.98 MHz)<br />
RCONbits.SWDTEN = 0; // Disable Watch Dog Timer<br />
while(OSCCONbits.LOCK != 1); // Wait for PLL to lock<br />
<br />
====UART====<br />
<br />
----<br />
*No change is required.<br />
<br />
====I2C====<br />
<br />
----<br />
*dsPIC33 supports upto 2 I<sup>2</sup>C devices. As a result, replace all I<sup>2</sup>C related registers with xxI2Cyy to xxI2C'''1'''yy. For examples:<br />
_SI2C1IF = 0; //Clear Slave interrupt<br />
_MI2C1IF = 0; //Clear Master interrupt<br />
_SI2C1IE = 0; //Disable Slave interrupt<br />
_MI2C1IE = 0; //Disable Master interrupt<br />
I2C1BRG = I2C_BRG; // Configure Baud rate<br />
I2C1CONbits.I2CEN = 1;<br />
...<br />
etc.<br />
<br />
====ADC====<br />
<br />
----<br />
*The ADC in dsPic33 is significantly different from that in dsPic30. Specifically, ADC in dsPic33 uses DMA to buffer the adc data. Replace the open, interrupt routine, add and remove codes as follows:<br />
<br />
unsigned int adc_bufA[ADC_MAX_CH] __attribute__((space(dma),aligned(256)));<br />
unsigned int adc_bufB[ADC_MAX_CH] __attribute__((space(dma),aligned(256)));<br />
unsigned int* ADC16Ptr; //Pointer to ADC register buffer, <br />
unsigned char adc_ch_select = 0; //Pointer to channel to be read from<br />
unsigned char adc_data_ready = 0; //Indicate if RAM data is ready for output<br />
unsigned int which_dma = 0; //indicate which adc_buf to be used<br />
<br />
void adc_open(void)<br />
{<br />
// Configure interrupt<br />
_AD1IF = 0; //clear ADC interrupt flag<br />
_AD1IE = 0; //disable adc interrupt<br />
AD1CHSbits.CH0NA = 0;<br />
// Configure analog i/o <br />
_TRISB0 = 1;<br />
_TRISB1 = 1; <br />
AD1PCFG = 0xFFFC; //Enable AN0 (Vref+) and AN1 (Vref-)<br />
AD1PCFGH = 0xFFFF; //AN16-AN31: Disabled<br />
// Configure scan input channels <br />
AD1CSSL = 0x0003; //0 => Skip, 1 => Scan<br />
AD1CSSH = 0x0000; //Skipping AN16-AN31<br />
// ADCCON4:<br />
AD1CON4bits.DMABL = 0; // Each buffer contains 1 word<br />
// ADCCON3:<br />
AD1CON3bits.SAMC = 1; //1TAD for sampling time<br />
AD1CON3bits.ADRC = 0; //Use system clock<br />
AD1CON3bits.ADCS = ADC_ADCS; //each conversion requires 14TAD<br />
// ADCCON2:<br />
AD1CON2bits.VCFG = 3; //External Vref+, Vref-<br />
AD1CON2bits.CSCNA = 1; //Scan input<br />
AD1CON2bits.SMPI = 1; //2 channels are scanned<br />
// ADCCON1:<br />
AD1CON1bits.FORM = 0; //[0:integer]; [2 fractional]; [3 siged fractional]<br />
AD1CON1bits.SSRC = 7; //auto covert, using internal clock source<br />
AD1CON1bits.ASAM = 1; //auto setting of SAMP bit<br />
AD1CON1bits.AD12B = 1; //12-bit, 1-channel ADC operation<br />
AD1CON1bits.ADDMABM = 0; // DMA buffers are built in scatter/gather mode<br />
AD1CON1bits.ADON = 1; // Turn on the A/D converter<br />
// DMA0 Configuration:<br />
DMA0CONbits.AMODE = 2; // Configure DMA for Peripheral indirect mode<br />
DMA0CONbits.MODE = 2; // Configure DMA for Continuous Ping-Pong mode<br />
DMA0PAD=(int)&ADC1BUF0; <br />
DMA0CNT = 1; // generate dma interrupt every 2 samples <br />
// same as SMPI because only 1 dma buffer per channel <br />
DMA0REQ = 13; // Select ADC1 as DMA Request source<br />
DMA0STA = __builtin_dmaoffset(adc_bufA); <br />
DMA0STB = __builtin_dmaoffset(adc_bufB);<br />
_DMA0IF = 0; // Clear the DMA interrupt flag bit<br />
_DMA0IE = 1; // Set the DMA interrupt enable bit<br />
DMA0CONbits.CHEN=1; // Enable DMA<br />
}<br />
<br />
void _ISR _DMA0Interrupt(void)<br />
{<br />
ADC16Ptr = (which_dma == 0)? adc_bufA : adc_bufB; //Update pointer<br />
adc_data_ready = 1;<br />
which_dma ^= 1; //Next buffer to be used<br />
_DMA0IF = 0; //Clear the DMA0 Interrupt Flag<br />
}<br />
<br />
static void adcAdd(unsigned char ch){<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
TRISB = TRISB | mask;<br />
AD1CSSL = AD1CSSL | mask; <br />
AD1PCFG = ~AD1CSSL;<br />
AD1CON2bits.SMPI++; //take one more sample per interrupt<br />
DMA0CNT++; <br />
}<br />
<br />
static void adcRm(unsigned char ch){<br />
unsigned int mask;<br />
mask = 0x0001 << ch;<br />
AD1PCFG = AD1PCFG | mask;<br />
AD1CSSL = ~AD1PCFG;<br />
AD1CON2bits.SMPI--; //take one less sample per interrupt<br />
DMA0CNT--; <br />
}<br />
<br />
====EEPROM====<br />
<br />
----<br />
*There is no EEPROM in dsPIC33 devices. Please consider to use an external EEPROM using I<sup>2</sup>C communication.<br />
<br />
====Simple PWM====<br />
<br />
----<br />
*No change is required.<br />
<br />
===Memory Map for dsPIC33FJ128GP306===<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 11.1 Memory Location<br />
! Type !! Start Address !! End Address !! Size<br />
|-valign="top"<br />
| Flash || 0x000000 ||0x0157FF || 86K<sup>[1]</sup><br />
|-valign="top"<br />
| +--Flash: Reset Vector || 0x000000 ||0x000003 || 4<br />
|-valign="top"<br />
| +--Flash: Interrupt Vector Table || 0x000004 ||0x0000FF || 252<br />
|-valign="top"<br />
| +--Flash: Alternate Vector Table || 0x000104 ||0x0001FF || 252<br />
|-valign="top"<br />
| +--Flash: User Program || 0x000200 ||0x0157FF || 85.5K<br />
|-valign="top"<br />
| Programming Executive || 0x800000 || 0x800FFF || 4K<sup>[1]</sup><br />
|-valign="top"<br />
| Config Registers || 0xF80000 || 0xF80017 || 24<br />
|-valign="top"<br />
| Device ID (0xE5) || 0xFF0000 || 0xFF0003 || 4<br />
|-<br />
|}<br />
[1] Each address is 16-bit wide. Every two addresses correspond to a 24-bit instruction. Each even address contains 2 valid bytes; each odd address contains 1 valid byte plus 1 phathom byte.<br><br />
<br />
===Custom Linker Script to Maximize Space for Constant Data===<br />
*Constant data declared using keyword '''const''' will be stored in the .const section in the flash memory.<br />
*Normally, during compilation, the linker will assign these data after the program code (.text section).<br />
*Since .const is accessed by auto-psv function, to maximize the space for constant data (32kb), the .const section needs to be aligned at 0x80000 boundary.<br />
*This requires the following change in linker script:<br />
<br />
__CONST_BASE = 0x8000;<br />
<br />
.text __CODE_BASE :<br />
{<br />
*(.reset);<br />
*(.handle);<br />
*(.libc) *(.libm) *(.libdsp); /* keep together in this order */<br />
*(.lib*);<br />
/* *(.text); deleted to maximize space for const data */<br />
} >program<br />
<br />
.const __CONST_BASE :<br />
{<br />
*(.const);<br />
} >program<br />
<br />
*If your program is large, after this change in linker script, function calls may involve large jump in the memory map (>32kB). As a result, you may need to enable the large code and large memory model during compilation. In such case, use the following options in your build path:<br />
-mlarge-code -mlarge-data<br />
*Meanwhile, functions that are defined in the standard C libraries, but are replaced with your own implementations (e.g. I/O stubs: open(), read(), write(), lseek(), ioctl() etc.) may have the following linker error:<br />
/usr/pic30-elf/lib//libc-elf.a(fflush.eo)(.libc+0x3c): In function '.LM11':<br />
: Link Error: relocation truncated to fit: PC RELATIVE BRANCH _write<br />
/usr/pic30-elf/lib//libc-elf.a(fclose.eo)(.libc+0x42): In function '.LM18':<br />
: Link Error: relocation truncated to fit: PC RELATIVE BRANCH _close <br />
*To resolve the problem, you need to place the functions in the .libc section rather than in the .text section, like this:<br />
#define LIBC_CODE_LOC __attribute__ ( (section(".libc")))<br />
<br />
int LIBC_CODE_LOC open(const char *pathname, int flags){ ... }<br />
int LIBC_CODE_LOC close(int fd){ ... }<br />
int LIBC_CODE_LOC write(int fd, void* buf, int count) { ... }<br />
int LIBC_CODE_LOC read(int fd, void* buf, int count) { ... }<br />
int LIBC_CODE_LOC ioctl(int fd, int request, void* argp) { ... }<br />
int LIBC_CODE_LOC lseek(int fd, int offset, int whence) { ... }<br />
<br />
===dsPicBootloader and dsPicProgrammer===<br />
*RTSP for dsPIC33F is different from dsPIC30F.<br />
**Row size changes from 32 instructions (96bytes) to 64 instructions (192 bytes)<br />
**Erase operation changes from 1 row to 8 rows<br />
**No EEPROM<br />
*With regards to the above changes, dsPicBootloader and dsPicProgrammer has been modified. In particular, dsPicProgrammer can be used to program both dsPic30F and dsPic33F devices. You can easily add your devices to the source code.<br />
<br />
<br />
==Downloads==<br />
{| border="1" cellspacing="0" cellpadding="5"<br />
|+ Table 12.1 Related software download links for dsPicBootloader and dsPicProgrammer<br />
! Program<br />
! Site 1<br />
! Site 2<br />
! Remarks<br />
|- valign="top"<br />
| JDK<br />
| [http://java.sun.com/javase/downloads/index.jsp website]<br />
| <br />
| Download latest JDK<br />
|- valign="top"<br />
| RXTX<br />
| [http://users.frii.com/jarvi/rxtx/download.html website]<br />
| <br />
| Download rxtx-2.1-7-bins-r2.zip or later<br />
|- valign="top"<br />
| dsPicBootloader v1.3<br />
| [http://chungyan5.no-ip.org/websvn/listing.php click]<br />
| [http://www.opencircuits.com/images/a/a7/DsPicBootloader_1_3_1.zip click]<br />
| Under "dsPicBootloader/", download bl_5011.s or bl_j128gp306.s<br />
|-valign="top"<br />
| dsPicProgrammer v1.3.5<br />
| [http://chungyan5.no-ip.org/websvn/listing.php click]<br />
| [http://www.opencircuits.com/images/9/9e/DsPicProgrammer_1_3_5.zip click]<br />
| Under "dsPicProgrammer/", dowload dsPicProgrammer.jar<br><br>Alternatively, if you want to compile yourself or modify the source code, download <br>all source files under "dsPicProgrammer/" '''plus''' RdFileIntelHex.java under <br>"IntelHexPaser/tags/0.02.00/".<br>You should also install RXTX on your local machine as recommended in the readme file.<br />
|- valign="top"<br />
| Ingenia's bootloader<br />
| [http://www.ingenia-cat.com/en/downloads.php website]<br />
| <br />
| Download original ingenia's bootloader<br />
|-<br />
|}</div>Yanhttp://www.opencircuits.com/index.php?title=PCB_Footprints&diff=11256PCB Footprints2007-11-21T03:26:15Z<p>Yan: Description og heavry symbol; cut the submit to gEDA, due to heavy type</p>
<hr />
<div>{| class="wikitable"<br />
! Manufacturer !! Description !! Available footprints<br />
|-<br />
|Trimble || Lassen iQ GPS Module || [[Media:Trimble Lassen iQ GPS Module.zip|Protel]]<br />
|-<br />
|(none) || Compact Flash IDE Connector || [[Media:Compact Flash IDE connector.zip|Protel]]<br />
|-<br />
|Linx Technologies || RF transmitters, RF receivers and USB transcievers || [[Media:Linx_Technologies.zip|Protel]]<br />
|-<br />
|Spark Fun Electronics || [[SFE_Footprint_Library|Old SFE Footprint Library]] || [[Media:SFE-Custom-Footprints.zip|Protel]] <br />
|-<br />
|Spark Fun Electronics || [[SFE_Footprint_Library_Eagle| Updated Eagle SFE Footprint Library]] || [[Media:SparkFunEagle-3-2-07.zip|Eagle]] <br />
|-<br />
| Cypress || PSoC microcontrollers || [http://www.psocdeveloper.com/forums/viewtopic.php?t=1029 Protel]<br />
|-<br />
| Microchip || PIC microcontrollers || [http://www.geda.seul.org/links.html gEDA ?] [http://www.isl.ee.boun.edu.tr/projects/motordriver/ ORCAD ?]<br />
|-<br />
| Atmel || Atmel AVR || [http://agentj.osk-net.pl/index.php/ProtelLibraries Protel]<br />
|-<br />
| Philips || ARM microcontrollers in LQFP-48 package || [http://k9spud.com/arm/lpc2103/ Eagle]<br />
|-<br />
| Misc. || Variety of footprints for gEDA/PCB || [http://www.luciani.org/geda/pcb/pcb-footprint-list.html PCB] [http://massmind.org/techref/app/PWB_libraries.htm Protel ] ||<br />
|}<br />
<br />
==gEDA Symbols and footprints==<br />
*[[Media:GEDA_sym_footprint.zip|un-test gEDA symbols and footprints]], [http://chungyan5.no-ip.org/WebServerDocs/open_data/eda/geda/libs/ Updated one]<br />
*All these Symbols are in heavy symbol. gEDA has already provided the light symbol to let us to modify, we create the heavy type for what we usually used and save our time to configure the symbol each time.<br />
<br />
== Other footprint libraries ==<br />
<br />
[http://freelabs.com/~whitis/opensymbol/ "Open Symbol Project" with Mark Whitis]<br />
"The Open Symbol Project aims to create an open collection of schematic symbols and PCB footprints released under a license that does not interfere with use in either commercial or free projects.<br />
...<br />
can easily be modified to accommodate various design rules."<br />
<br />
What can we do to help the Open Symbol Project?<br />
<br />
-----<br />
<br />
[http://www.pcb123.com/community/content/modules.php?name=screen_shots PCB123 Libraries] includes some footprint libraries (and a gallery of PCBs).<br />
<br />
----<br />
See also the [[SFE Footprint Library Eagle]].<br />
<br />
-----</div>Yanhttp://www.opencircuits.com/index.php?title=Ethernet_Module&diff=6491Ethernet Module2007-08-21T03:58:43Z<p>Yan: Architecture</p>
<hr />
<div>==Introduction==<br />
*This project aims to develop an Ethernet Module, to be used in conjunction with a 8/16 bits embedded system such as the [http://opencircuits.com/DsPIC30F_5011_Development_Board dsPic33F development board].<br />
*The entire Ethernet Module consists of:<br />
#Hardware: a LAN card based on [http://www.davicom.com.tw/eng/index.htm Davicom] DM9000A chip<br />
#Software: a TCP/IP stack based on [http://www.sics.se/~adam/uip/ uIP] 1.0 or [http://savannah.nongnu.org/projects/lwip/ lwIP]<br />
<br />
<br />
==Hardware==<br />
===Component List===<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
! Special Item !! Description !! Quantity<br />
|-valign="top"<br />
| [http://www.davicom.com.tw/big5/download/Data%20Sheet/DM9000A-DS-F01-101906.pdf DM9000AEP] || Ethernet Controller || 1<br />
|-<br />
| [http://www.hanrun.com/hr/upfile/2_1_113.pdf HR911102A] || RJ45 Connector with Integrated Magnetics for 10/100 Base-TX || 1<br />
|-<br />
| [http://ww1.microchip.com/downloads/en/DeviceDoc/21749F.pdf 93LC46B-I/SN] || 1K Serial EEPROM || 1 (Optional)<br />
|-<br />
| 25MHz Crystal || Crystal || 1<br />
|-<br />
| 22pF || For Crystal Use || 2<br />
|-<br />
| 220uF || For RXVDD25/TXVDD25 || 1<br />
|-<br />
| 49.9ohm || For RX+/RX-/TX+/TX- || 4<br />
|-<br />
| 6.8kohm || For BGRES/BGGND || 1<br />
|-<br />
| 510ohm || For LEDs|| 2<br />
|-<br />
|}<br />
<br />
===Circuit and PCB===<br />
in [http://chungyan5.no-ip.org/vc/?root=ethernet gEDA format]<br />
and its gEDA [http://www.opencircuits.com/PCB_Footprints#gEDA_Symbols_and_footprints sym and footprints]<br />
<br />
<br />
==Software Driver==<br />
*Download [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/dm9000a.c?root=freertos_posix&view=markup dm9000a.c]<br />
*Download [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/include/dm9000a.h?root=freertos_posix&view=markup dm9000a.h]<br />
*Base on [http://www.freertos.org/ FreeRTOS] and [http://opencircuits.com/DsPIC30F_5011_Development_Board dsPIC33 platform]<br />
*Using POSIX-like API:<br />
**'''int dmfe_open(int flags)''': initialize the Ethernet controller for 10MHz Half-Duplex<br />
**'''int dmfe_close()''': turn off the PHY layer<br />
**'''int dmfe_read(void)''': copy a packet to the default buffer<br />
**'''int dmfe_write(unsigned char device, unsigned char *buf, int count)''': copy count bytes of the data from buf and transmit<br />
**'''void dmfe_interrupt(void)''': process the transmit interrupt from DM9000A<br />
<br />
<br />
==TCP/IP Stack==<br />
*uIP and lwIP are light weight TCP/IP Stack designed for 8-bit/16-bit embedded systems.<br />
<br />
----<br />
<br />
===uIP===<br />
*Develped by Adam Dunkels of the Networked Embedded Systems group at the Swedish Institute of Computer Science.<br />
*uIP is under the [http://www.sics.se/~adam/uip/index.php/License BSD-style license]<br />
====CVS Repository====<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
! Attribute !! Value<br />
|-valign="top"<br />
| Host || uip-stack.cvs.sourceforge.net<br />
|-<br />
| Repository Path || /cvsroot/uip-stack<br />
|-<br />
| Connection Type || pserver<br />
|-<br />
| User || anonymous<br />
|-<br />
|}<br />
*Changes made to CVS Repository (tag: HEAD)<br />
**Comment out all DEBUG_PRINTF(...) in uip.c<br />
***Line 1, 323, 910, 1015, 1070, 1863, 1868, 1869<br />
====Porting====<br />
*Include the following files to use the uIP stack<br />
**timer.c<br />
**uip.c<br />
**uip_arp.c<br />
**psock.c<br />
*The following files have been created to port uIP 1.0 to dsPic33F development board using FreeRTOS<br />
*[http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/clock-arch.c?root=freertos_posix&view=markup clock-arch.c]: return the os tick counts since the system is turned on.<br />
*[http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/drivers/include/clock-arch.h?root=freertos_posix&view=markup clock-arch.h]: a constant specifying the number of os ticks in one second.<br />
*[http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/dspic33/rackmount/04_uip/include/uip-conf.h?root=freertos_posix&view=markup uip-config.h]: configuration for your application.<br />
<br />
----<br />
<br />
===lwIP===<br />
*lwIP is a small independent implementation of uIP.<br />
*It is more powerful than uIP but requires more memory.<br />
*lwIP is under the [http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5 Modified BSD License]<br />
====CVS Repository====<br />
{|border="1" cellspacing="0" cellpadding="5"<br />
! Attribute !! Value<br />
|-valign="top"<br />
| Host || cvs.savannah.nongnu.org<br />
|-<br />
| Repository Path || /sources/lwip<br />
|-<br />
| Connection Type || pserver<br />
|-<br />
| User || anonymous<br />
|-<br />
|}<br />
====Porting====<br />
*To be added<br />
<br />
<br />
==uIP Ethernet Application==<br />
<br />
===DHCP Client===<br />
*Enable UDP in "uip-config.h"<br />
#define UIP_CONF_UDP 1<br />
*Make sure your uip buffer size is large enough (DHCP messages from some servers can be more than 500 bytes). In my setting, I use 1536 in "uip-config.h"<br />
#define UIP_CONF_BUFFER_SIZE 1536<br />
*Include the dhcpc.h header file in "uip-config.h"<br />
#include "dhcpc.h"<br />
*Change PT_WAIT_UNTIL(...) to PT_YIELD_UNTIL(...) in line 259 and 276 in "dhcpc.c" [This is a known bug in dhcpc.c]<br />
*In your main loop, initialize your MAC address and DHCP if UIP_FIXEDADDR is 0 in "uip-opt.h", for example:<br />
int main(void)<br />
{<br />
uip_ipaddr_t ipaddr;<br />
struct timer periodic_timer, arp_timer;<br />
struct uip_eth_addr mac = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06};<br />
<br />
timer_set(&periodic_timer, CLOCK_SECOND / 2);<br />
timer_set(&arp_timer, CLOCK_SECOND * 10);<br />
<br />
tapdev_init();<br />
uip_init();<br />
<br />
uip_setethaddr(mac);<br />
dhcpc_init(&mac, 6);<br />
<br />
while(1){<br />
//normal codes goes here<br />
}<br />
}<br />
*Implement dhcpc_configured(). This function will be called after DHCP client has obtained an IP address. Basically, you have to at least set your IP address, subnet mask and default gateway, for example,<br />
void dhcpc_configured(const struct dhcpc_state *s)<br />
{<br />
uip_sethostaddr(s->ipaddr);<br />
uip_setnetmask(s->netmask);<br />
uip_setdraddr(s->default_router);<br />
<br />
//you can print your ip addr to your console/lcd to see if you get a valid ip address<br />
}<br />
*An example of using DHCP Client in the dsPic33F development board can be found [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/common/app_http.c?root=freertos_posix&view=markup here].<br />
<br />
===Web Server===<br />
*Include the "webserver.h" header file in "uip-config.h"<br />
#include "webserver.h"<br />
*Modify httpd-fs.h<br />
**HTTPD_FS_STATISTICS set to 0<br />
*Create a website using HTML tags with/without Javascript<br />
*Modify httpd-fs.c<br />
**changed #include "httpd-fsdata.c" to #include <httpd-fsdata.c> <br />
*Generate httpd-fsdata.c for your website by executing '''perl makefsdata''' under your web root directory.<br />
====add-on====<br />
*The Web Server included in uIP 1.0 has been designed to load/reload the entire page (either html/shtml files) in response to a HTTP GET command, e.g.<br />
GET /index.html HTTP/1.1<br />
GET /abc.shtml HTTP/1.1<br />
*As a result, if the webpage is required to refresh the dynamic data periodically, the surfing experience will be degraded by the large transfer of datastream.<br />
*In consideration of the above issue, a solution is proposed here, so that the webserver can handle this kind of cgi HTTP-request<br />
GET /abc.shtml?val=500.0&button=Set HTTP/1.1<br />
*Modify httpd.c<br />
**added #include "httpd-hget.h" in line 63<br />
**added httpd_hget(s->filename) in line 224<br />
*Create httpd-hget.h<br />
**added to generate dynamic pages, e.g. /abc.shtml?button=Refresh<br />
#ifndef __HTTPD_HGET_H__<br />
#define __HTTPD_HGET_H__<br />
extern void httpd_hget(char *name);<br />
#endif<br />
*Create httpd-hget.c<br />
**an example is shown [http://chungyan5.no-ip.org/vc/tags/1.09.05/demo_posix/dspic/dspic33/rackmount/04_uip/uip/httpd-hget.c?root=freertos_posix&view=markup here]<br />
<br />
<br />
==SNMP Agent==<br />
*Simple Network Management Protocol (SNMP) is a standard protocol to access variables to remote device via the Internet.<br />
*It belongs to the Application Layer, as in HTTP.<br />
*If a device is SNMP compatible, any SNMP compatible host system can monitor and control that device.<br />
<br />
===Components in a SNMP System===<br />
*Network Management Station (NMS)<br />
**This is a client, initiating SNMP communication.<br />
**This can be a PC with an NMS software (e.g. [http://nino.sourceforge.net/nino/index.html NINO]), polling data from the SNMP agents periodically.<br />
*SNMP Agents<br />
**These are servers, responding to one or multiple NMS requests.<br />
*Management Information Base (MIB)<br />
**A special collection of variables managed by the SNMP agents.<br />
**MIB has a tree-like structure.<br />
**An Object Identifier (OID) is given for each node.<br />
**Data are stored at the end-nodes.<br />
**Private variables may be constructed under the "enterprise" sub-tree.<br />
**The OID for "enterprise" can be obtained from [http://www.iana.org/cgi-bin/enterprise.pl Internet Assigned Number Authority (IANA)].<br />
<br />
===Abstract Syntax Notation===<br />
*Each MIB variable contains several attributes, such as data type, access type and object identifier.<br />
*Abstract Syntax Notation version 1 (ASN.1) is a language to define these attributes in SNMP.<br />
<br />
<br />
==Architecture==<br />
<pre><nowiki><br />
+------------------------------------+<br />
| application |<br />
| |<br />
+--------+--------+---------+--------+<br />
| web | dhcp | snmp | ... |<br />
| Server | | | |<br />
| | | | |<br />
|--------+--------+---------+--------+<br />
| ethernet | uip |<br />
| control | |<br />
+-----------------+------------------+<br />
| driver |<br />
+------------------------------------+<br />
</nowiki></pre><br />
<br />
<br />
==Reference==<br />
===DM9000A===<br />
*[http://www.davicom.com.tw/eng/products/dm9000a.htm DM9000A Description]<br />
*[http://www.davicom.com.tw/big5/download/Data%20Sheet/DM9000A-DS-F01-101906.pdf DM9000A Datasheet]<br />
*[http://www.davicom.com.tw/big5/download/AC/dm9000a/DM9000A%20circuit_EMI_052306.pdf Application Circuit]<br />
*[http://www.davicom.com.tw/big5/download/LayoutGuide/DM9000A_9010-LG-V11_031706.pdf Layout Guidelines]<br />
*[http://www.davicom.com.tw/big5/download/ApplicationNote/DM9000A%20Application%20Notes%20Ver%201_20_101906.pdf Application Note]<br />
*[http://www.davicom.com.tw/eng/download/Driver/driver_9000.htm DM9000A Official Drivers]<br />
===dsPic33F Development Board===<br />
*[http://opencircuits.com/DsPIC30F_5011_Development_Board dsPic33F Development Board]<br />
===uIP===<br />
*[http://www.sics.se/~adam/uip/index.php/Main_Page uIP Description]<br />
*[http://www.sics.se/~adam/uip/index.php/Documentation uIP Documentation]<br />
*[http://www.sics.se/~adam/uip/index.php/Download Download]<br />
*[http://sourceforge.net/cvs/?group_id=186227 CVS Repository]<br />
===lwIP===<br />
*[http://savannah.nongnu.org/projects/lwip/ lwIP Description]<br />
*[http://www.nongnu.org/lwip/ Documentation]<br />
===HTML===<br />
*[http://www.w3schools.com/default.asp W3 Schools]: Learning how to write HTML and JavaScript<br />
*[http://www.nvu.com/index.php Nvu]: Open source HTML Editor<br />
===SNMP===<br />
*[http://www.snmplink.org SNMP Link]: Information on SNMP Agents<br />
*[http://pen.iana.org/pen/PenApplication.page IANA]: Applying a Private Enterprise Number</div>Yanhttp://www.opencircuits.com/index.php?title=Ethernet_Module&diff=5738Ethernet Module2007-07-31T09:27:51Z<p>Yan: gEDA sym and footprints</p>
<hr />
<div>==Desription==<br />
Mainly working with for 8/16 bits MCU<br />
<br />
==Which Chips==<br />
<br />
===DM9000A===<br />
<br />
====Web Site====<br />
http://www.davicom.com.tw/big5/products/dm9000a.htm<br />
<br />
====Circuit and PCB====<br />
in [http://chungyan5.no-ip.org/vc/?root=ethernet gEDA format]<br />
and its gEDA [http://www.opencircuits.com/PCB_Footprints#gEDA_Symbols_and_footprints sym and footprints]<br />
<br />
====Driver====<br />
Base in Freertos and dspic platform, see http://chungyan5.no-ip.org/vc/tags/1.07.08/demo_posix/dspic/drivers/dm9000a.c?root=freertos_posix&view=markup</div>Yanhttp://www.opencircuits.com/index.php?title=PCB_Footprints&diff=5737PCB Footprints2007-07-31T09:26:08Z<p>Yan: /* gEDA Symbols and footprints */ Updated gEDA Symbol and footprints</p>
<hr />
<div>{| class="wikitable"<br />
! Manufacturer !! Description !! Available footprints<br />
|-<br />
|Trimble || Lassen iQ GPS Module || [[Media:Trimble Lassen iQ GPS Module.zip|Protel]]<br />
|-<br />
|(none) || Compact Flash IDE Connector || [[Media:Compact Flash IDE connector.zip|Protel]]<br />
|-<br />
|Linx Technologies || RF transmitters, RF receivers and USB transcievers || [[Media:Linx_Technologies.zip|Protel]]<br />
|-<br />
|Spark Fun Electronics || [[SFE_Footprint_Library|Old SFE Footprint Library]] || [[Media:SFE-Custom-Footprints.zip|Protel]] <br />
|-<br />
|Spark Fun Electronics || [[SFE_Footprint_Library_Eagle| Updated Eagle SFE Footprint Library]] || [[Media:SparkFunEagle-3-2-07.zip|Eagle]] <br />
|-<br />
| Cypress || PSoC microcontrollers || [http://www.psocdeveloper.com/forums/viewtopic.php?t=1029 Protel]<br />
|-<br />
| Microchip || PIC microcontrollers || [http://www.geda.seul.org/links.html gEDA ?] [http://www.isl.ee.boun.edu.tr/projects/motordriver/ ORCAD ?]<br />
|-<br />
| Atmel || Atmel AVR || [http://agentj.osk-net.pl/index.php/ProtelLibraries Protel]<br />
|-<br />
| Philips || ARM microcontrollers in LQFP-48 package || [http://k9spud.com/arm/lpc2103/ Eagle]<br />
|-<br />
| Misc. || Variety of footprints for gEDA/PCB || [http://www.luciani.org/geda/pcb/pcb-footprint-list.html PCB] [http://massmind.org/techref/app/PWB_libraries.htm Protel ] ||<br />
|}<br />
<br />
==gEDA Symbols and footprints==<br />
*[[Media:GEDA_sym_footprint.zip|un-test gEDA symbols and footprints]], [http://chungyan5.no-ip.org/WebServerDocs/open_data/eda/geda/libs/ Updated one]<br />
*ToDo<br />
**after test with gEDA symbol and footprint tools, then these libraries can submit to gEDA web sites for official one.<br />
<br />
== Other footprint libraries ==<br />
<br />
[http://freelabs.com/~whitis/opensymbol/ "Open Symbol Project" with Mark Whitis]<br />
"The Open Symbol Project aims to create an open collection of schematic symbols and PCB footprints released under a license that does not interfere with use in either commercial or free projects.<br />
...<br />
can easily be modified to accommodate various design rules."<br />
<br />
What can we do to help the Open Symbol Project?<br />
<br />
-----<br />
<br />
[http://www.pcb123.com/community/content/modules.php?name=screen_shots PCB123 Libraries] includes some footprint libraries (and a gallery of PCBs).<br />
<br />
<br />
-----</div>Yanhttp://www.opencircuits.com/index.php?title=Techniques&diff=5369Techniques2007-07-20T06:08:23Z<p>Yan: Enclosure</p>
<hr />
<div>== Printed circuit board fabrication ==<br />
<br />
<br />
=== Homebrew ===<br />
* [[Toner Transfer]] -- This method involves laser printing your PCB design onto paper, then transferring toner onto copper-clad board.<br />
* [[Photoetching]] -- Exposure of PCB designs onto photosensitized copper-clad board.<br />
* [[Chemical Etchants]]<br />
<br />
=== Commercial PCB fabrication ===<br />
* [[Submitting PCB's for fabrication]] -- Common processes for submitting PCB's for fabrication.<br />
* [[PCB Manufacturers]]<br />
<br />
== Circuit construction (non PCB) ==<br />
<br />
* [[Solderless protoboard]] ([http://en.wikipedia.org/wiki/Breadboard Wikipedia:Breadboard])<br />
* [[Point-to-point]] ([http://en.wikipedia.org/wiki/Point-to-point_construction Wikipedia:Point-to-point construction])<br />
* [[Wirewrap]] ([http://en.wikipedia.org/wiki/Wire_wrap Wikipedia:Wire Wrap])<br />
* [[Dead bug style]] -- and a similar method, [http://ciphersbyritter.com/RADELECT/BREADBD/BREADBD.HTM "A Modern Breadboarding Technology: Insulating Pads Soldered to a Ground Plane"]<br />
* [[Manhattan style]]<br />
<br />
[[http://www.techlib.com/electronics/construction.html "Construction Ideas"]] has nice photographs of the above circuit construction techniques.<br />
<br />
== Soldering techniques ==<br />
<br />
* [[Basic soldering]] -- How to use a soldering iron.<br />
* Surface Mount<br />
** [[Skillet reflow]]<br />
** [[Toaster oven reflow]]<br />
** [[Hot air soldering]]<br />
* [[Rework]] -- Techniques for fixing mistakes, or for adding new features to a board that ''almost'' does what you want.<br />
** [http://workmanship.nasa.gov/lib/insp/2%20books/links/sections/302_jumper%20wires.html official NASA recommendations for adding discrete wiring ("jumper wires") to PCBs]<br />
<br />
(Have you seen this [http://www.hackaday.com/2007/06/04/cnc-solder-paste-pick-n-place/ CNC solder paste/pick n place] ?)<br />
<br />
== software design tools ==<br />
<br />
Some people still build circuits without ever using any software tools.<br />
For complicated circuits, software design tools can save a lot of time.<br />
<br />
Here we list "suites" that combine schematic capture, component editor for the components used in schematic capture, circuit simulation, PCB layout, autorouter, and footprint editor for the footprints used in PCB layout.<br />
(Is there another place for listing stand-alone tools such as a switching power supply "wizard" and a RF analysis tool?)<br />
<br />
Quite often people mix-and-match tools -- using a schematic capture from one suite to generate pretty schematics and a netlist, then importing the netlist a third party Specctra autorouter, then importing the result into a PCB layout program from another suite for the final manual clean-up and design rule checking.<br />
<br />
In no particular order:<br />
<br />
* gEDA http://geda.seul.org/ ; [http://geda.seul.org/wiki/ gEDA wiki] -- free version; open source. Includes schematic and [http://sourceforge.net/projects/pcb/ PCB].<br />
* McCAD EDS Lite http://mccad.com/ -- free demo version available for download, 200 pin limit<br />
* McCAD EDS SE is free with the book [http://applefritter.com/replica "Apple I Replica Creation" ] -- supports 750 pins, 11"x17" sheet size, 6-8 data layers. <tangent>(any useful tips in this book for those who want to build a CPU from scratch?) <reply>No, there are not. The book is more entry-level. - Tom Owad</reply></tangent><br />
* FreePCB http://www.freepcb.com/ -- free version; open source, Win32 PCB Design Software<br />
* TinyCAD http://tinycad.sourceforge.net/ -- free version; open source, Win32 Schematic Drawing Software<br />
* KiCad http://kicad.sourceforge.net/ and http://www.lis.inpg.fr/realise_au_lis/kicad/ -- free version; open source, eda suite, Both Win32 and Linux Version<br />
* Express PCB http://expresspcb.com/ -- "free" software<br />
<br />
* Protel DXP http://altium.com/ ; [http://techref.massmind.org/techref/app/protel.htm independent Protel users FAQ]<br />
* Eagle http://cadsoftusa.com/ ; http://cadsoft.de/ ; [http://www.sparkfun.com/tutorial/PCB/eagle-output-tutorial.htm Eagle tutorial from Sparkfun] ; [http://www.makezine.com/blog/archive/2006/03/how_to_make_a_custom_library_p.html another Eagle tutorial] -- free demo version available<br />
* DipTrace http://diptrace.com/ -- free 30 day demo version available for download.<br />
* WinQcad http://winqcad.com/ -- free demo version (up to 499 pins) available for download<br />
* Rimu Schematic and Rimu PCB http://www.hutson.co.nz/ -- ???<br />
* SuperCAD and SuperPCB http://mentala.com/<br />
<br />
''(Should I make a huge grid here, with checkmarks for "runs on Mac", "runs under Linux", "open source", "includes autorouter", etc. ?)''<br />
(yes!! yes you should!! now get back to work slave!!)<br />
<br />
Another [http://techref.massmind.org/techref/pcbcads.htm list of software design tools at the Massmind].<br />
<br />
Is there any way to objectively compare these tools?<br />
How well did they do at the<br />
[http://www.pcbwest.com/topgun/ PCB Top Gun contest] ?<br />
<br />
=== Checklist for "The flow of PCB fabrication/PCB 製作流程" using Software Design Tool===<br />
*Format and shape of PCB are conformed./底板的幾何圖形和尺寸確認<br />
*Via size and location are conformed./定位和開孔尺寸確認<br />
*Fixed location item are placed on suitable place./對有所要求之硬件放置的明白確認<br />
*A one-first PCB silk layout is made./做一張1:1的PCB白油圖<br />
*All item get enough clearance between them./所有硬件排放後檢查相鄰是否過於緊貼<br />
*All vias get enough size to install them components./所有孔徑是否符合要求<br />
*Make sure no worng footprint is created./肯定了腳銲盤無錯誤<br />
*PCB is drew./完成了PCB<br />
*Netlist is ran and got a no error result./執行netlist指令直無錯誤<br />
*DRC is ran and got a no error result./執行DRC直至無錯誤<br />
*Location of item is reasonable./模擬實物放置是否合理<br />
*All items are put on to a hard copy of PCB./放置所有零件在影印本的PCB上 <br />
*Overall is checked./全面檢查確認無誤<br />
<br />
And then the Gerbers are sent to a [[PCB_Manufacturers]].<br />
<br />
== embedded system programming and testing ==<br />
<br />
* Many systems use [[JTAG]] for programming and testing. (Such as [http://en.wikibooks.org/wiki/Atmel_AVR Atmel AVR embedded systems]]).<br />
* Other systems use some other kind of in-circuit programming.<br />
* Some people use [http://en.wikibooks.org/wiki/Embedded_Systems/Bootloaders_and_Bootsectors bootloaders] to make re-programming a little quicker.<br />
<br />
== Enclosure ==<br />
<br />
* The Earth Signal should short to whole metal Case<br />
* Digital/Analog GND should separate to this Earth Signal, and should connect a Y-cap. to filter the noise between them.<br />
* Attention: do not place near between Earth Signal and Digital/Analog GND, otherwise some spark come out, and affect your whole system.<br />
<br />
== further reading ==<br />
<br />
* [http://airborn.com.au/method/ "Electronics Design" from Airborn] gives an overview of the complete process: specification, (schematic) circuit design, layout, prototypes, firmware, pilot run, production.<br />
* EDA electronic design automation software is a subset of CAD in general. Is there a wiki that discusses CAD in general? Until I find it, I'm going to post these tools here: "Google SketchUp is a powerful yet easy-to-learn 3D software tool" http://sketchup.google.com/ ; "Inkscape is the best tool for SVG standard vector graphics" http://wiki.inkscape.org/ ; Visual Wiki http://visualwiki.org/<br />
* [http://www.national.com/rap/Story/0,1562,18,00.html "What's All This Ground Noise Stuff, Anyhow?"] by Robert A. Pease<br />
* [http://www.elecdesign.com/Articles/ArticleID/6150/6150.html "What's All This Teflon Stuff, Anyhow?"] by Robert A. Pease -- explains a situation using lots of metal (instead of carefully insulating everything with lots of Teflon) causes less noise. Also mentions "why am I telling you all of these details? If I design a tester with greatly improved performance to help me test a really high-performance product, why should I tell all our competitors so that anybody in the world can test their products using the improved tester? Why should I give away all of these hard-earned secrets?" and gives some very good reasons.<br />
* [http://groups.google.to/group/sci.electronics.design/browse_thread/thread/889153f0e77b1718/fcaac532bb6d4b12?fwc=1 sci.electronics.design: EDN: Measuring Nanoamperes] discusses some ways to measure extremely small currents.<br />
<br />
<br />
<br />
[[Category:Techniques]]</div>Yanhttp://www.opencircuits.com/index.php?title=Ethernet_Module&diff=5347Ethernet Module2007-07-19T08:32:41Z<p>Yan: create for DM9000A with circuit and driver</p>
<hr />
<div>==Desription==<br />
Mainly working with for 8/16 bits MCU<br />
<br />
==Which Chips==<br />
<br />
===DM9000A===<br />
<br />
====Web Site====<br />
http://www.davicom.com.tw/big5/products/dm9000a.htm<br />
<br />
====Circuit and PCB====<br />
in [http://chungyan5.no-ip.org/vc/?root=ethernet gEDA format]<br />
<br />
====Driver====<br />
Base in Freertos and dspic platform, see http://chungyan5.no-ip.org/vc/tags/1.07.08/demo_posix/dspic/drivers/dm9000a.c?root=freertos_posix&view=markup</div>Yanhttp://www.opencircuits.com/index.php?title=Projects&diff=5346Projects2007-07-19T04:11:24Z<p>Yan: Ethernet Module</p>
<hr />
<div>===Homemade MIDI turntable===<br />
Cheap and simple homemade MIDI turntable with GPL2 license. Using a ATmega, a HDNS-2000 optical mouse encoder, GCC-AVR, AVR-Libc and FreeRTOS. [http://casainho.net/tiki-index.php?page=Homemade+midi+turntable Homepage of Homemade MIDI turntable].<br />
<br />
=== [[ARMUS Embedded Linux Board]] ===<br />
An ARM920T board running Linux at 200 Mips with sound, Ethernet, CAN, 48+ bidirectionnal IOs and 4 DSPs for motor control (DC, Servos, etc...). Built as a student proof robotics design platform.<br />
<br />
=== [[Programmable Chip EEG]] ===<br />
The Programmable Chip EEG is a Multi-channel electroencephalograph that could be a brain-computer interface.<br />
<br />
=== [[Open Mobile Gadgets]] -- open source, open hardware, mobile phone ===<br />
An open source, open hardware mobile phone in its preliminary development.<br />
<br />
=== [[Music Player]]s including MP3 players === Nguyen Xuan Truong Tin6 k48<br />
<br />
[[TRAXMOD]] Open source MOD music player for dsPIC/ARM microcontrollers.<br />
<br />
=== [[PG31 GPS RS232 Dev Board]] ===<br />
A simple RS232 example project that takes 3.3V TTL serial and outputs to a super-common RS232 connection. Insto-NMEA!<br />
<br />
=== [[RS232 Dev Board]] ===<br />
A simple RS232 example project that takes all the power it needs from the serial port. Use it to power your microcontroller and communicate between serial port and microcontroller. Takes advantage of the fact that pc serial ports will accept 0-5V rather than the RS232 standard of around negative 10V to positive 10V. Very convenient - no external power required! Note that you may use either a 5.1V zener or a 5V regulator.<br />
<br />
=== [[RS232 RS485 USB Converter Board]] ===<br />
Aim to build a general Converter between different Interfaces.<br />
<br />
=== [[PG31 GPS USB Dev Board]] ===<br />
A great example project using the CP2102 USB to TTL UART IC as well as some basic battery holder info.<br />
<br />
=== [[Chalk Roach|Number Six]] ===<br />
"#6" (the son of Chalk Roach)<br />
is a ultra simple microcontroller development board for Atmel ATmega32 = 16MHz, 2KB SRAM, 16KB Flash<br />
<br />
=== LED displays ===<br />
<br />
* [[24" Wall Clock]] A really big wall clock. Why? Well, cause it might look cool? Probably not. But we do use GPS to get the time! Groovy.<br />
* [[POV display]] that spins around, giving the illusion of a large display. ([[User:DavidCary|DavidCary]])<br />
<br />
=== [[Cellular Rotary Phone]] ===<br />
An indepth breakdown of the Port-O-Rotary. Some clues to help you avoid audio problems with the GM862.<br />
<br />
=== [[Das Brewmeister!]] and [[Fermenter Controller]] ===<br />
* [[Das Brewmeister!]] : An attempt to wirelessly monitor temperatures of fermentation vessels<br />
* [[Fermenter Controller]] : A web available fermenter vessel controller. Uses PICs, [[I2C]], Rs232 and python.<br />
<br />
=== [[Home controller]] ===<br />
Program your appliances to operate automatically in conjunction with your weekly and daily schedule, manually turn them on/off from your PC or use the controller as a process ON/OFF controller to regulate some kind of physical variable to the desired value.<br />
<br />
=== [[Interactive Lock Box]] ===<br />
An interesting project using an accelerometer and capacitive touch ICs.<br />
<br />
=== [[Motor driver]] (H-bridge) ===<br />
<br />
=== [[atomic microscope]] ===<br />
An atomic-resolution microscope.<br />
* STM (scanning tunnelling microscope)<br />
* AFM (atomic force microscope)<br />
<br />
=== [[BlueICE]] ===<br />
A bluetooth JTAG ICE debugger for AVR's!!!<br />
<br />
=== [[Sortof-Networked RFID Reader]] ===<br />
A 125Khz RFID Reader with a simple RS232 based ring network - to allow connection of multiple units to the same control computer.<br />
<br />
''Consider using [http://zytrax.com/tech/layer_1/cables/tech_rs232.htm#rj45 "RS-232D", aka "EIA/TIA-561"]. It has all the same wires and voltages as RS-232, but specifies a RJ45 connector.''<br />
<br />
''Also consider RS-485.''<br />
<br />
(What is the name of the standard for RS-485 on RJ14 ("4 wire RJ-11") or RJ45 ?)<br />
(Ethernet? =P)<br />
<br />
=== Battery charger ===<br />
<br />
See [http://elecdesign.com/Article/ArticleID/1823/1823.html "Build A Smart Battery Charger Using A Single-Transistor Circuit"] by Ejaz ur Rehman.<br />
But be sure to read the "Reader Comments" at the end.<br />
The suggestion to add a zener diode is a good idea.<br />
<br />
=== the Open Graphics Project ===<br />
<br />
[http://linux.wordpress.com/2006/07/19/introducing-the-open-graphics-project/ the Open Graphics Project]<br />
a project started by chip-designer Timothy Miller.<br />
His goal, along with the rest of the project, known as the “Open Graphics Foundation” is to make a 3D accelerated video card which is fully documented, free-licensed, and open source.<br />
See [http://wiki.duskglow.com/tiki-index.php?page=Open-Graphics the Open Graphics wiki].<br />
<br />
=== [[Amiga floppy project]] ===<br />
<br />
The Amiga floppy project:<br />
designing, building, and programming an adapter to allow PCs to read from Amiga floppies.<br />
"This is really designed to be a community project(hence the blog with progress reports)."<br />
<br />
This project is the building of an external USB amiga floppy drive controller. It sits between the USB port on a Windows PC, and a regular PC floppy drive. It will allow the PC to create .ADF images from an amiga floppy disk. This device is based on a Parallax SX28 microcontroller, uses Ramtron FRAM memory for temporary track storage, and uses another Parallax component for the USB interface.<br />
<br />
See http://www.techtravels.org/amiga/amigablog for the latest in the blow by blow attempts to get this thing off the ground!!<br />
<br />
=== Irsensor-a ===<br />
<br />
Infrared Proximity Sensor Alfa<br />
[http://www.kedo.com.mx/modules/content/index.php?id=3 Infrared Proximity Sensor Alfa in www.kedo.com.mx]<br />
<br />
The Infrared Proximity Sensor Alfa is a sensor to detect objects that can reflect infrared light. It has the following characteristics.<br />
* Designed to detect objects that are close and can reflect infrared lights.<br />
* It has a Infrared Transmitter to eliminate the dependency of solar lighting. So It can be used in the night.<br />
* It has a Infrared Receiver that detects the closest object that reflects the infrared lights.<br />
* It has an incorporated voltage regulator<br />
* The output is a constant 5V when it is active and 0V when no detection.<br />
* You can change the proximity threshold with a potentiometer.<br />
<br />
=== [[dsPIC30F 5011 Development Board]] ===<br />
A development board using Microchip dsPIC30F5011, a 5V based 16-bit microcontroller with DSP functions, EEPROM, ADC, PWM and communciation ports of UARTs, I2C, SPI etc. Contains concise information on:<br />
#Development environments (IDE)<br />
#External programming methods (ICSP Programming using ICD2 Programmer)<br />
#Bootloader implementation (RTSP)<br />
#Software development tips based on POSIX concepts<br />
#Basic conversion tips to target board using Microchip dsPIC33FJ128GP306, a pin-to-pin compatible 3.3V microcontroller<br />
<br />
=== [http://balloonboard.org Balloon Xscale ARM+FPGA dev board] ===<br />
The Balloon project has produced Balloon3, a high-performance ARM board designed for use by OEMs and Higher education. Spec is PXA270 (583Mhz), FPGA or CPLD, 1GB flash, 784MB RAM, USB (master, slave, OTG), CF slot, expansion bus, 16-bit bus, I2C, LCD, serial, audio. Very low power in CPLD confiuguration. Small, light. Various add-on boards: VGA LCD driver, robot motor driver+A/D, digital IO. Released under the Balloon Open Hardware license, which allows anyone to manufacture and for people to make derivatives. The expansion bus allows balloon to be used as the computing component for various special-purpose devices.<br />
<br />
=== scavenge ===<br />
<br />
Some people derive an inordinate amount of pleasure from building semi-useful objects from zero-cost junk.<br />
<br />
In the electronics field, most of the stuff built from scavenged components falls into 2 categories:<br />
* ham radio transmitters and receivers -- built from a few transistors, caps, resistors, and wire<br />
* BEAM robotics -- built from the above plus motors, solar cells, ...<br />
<br />
According to http://coprolite.com/art12.html ,<br />
"I'd love to hear about where you found your 8048. Take a picture of the host that you remove it from (CD player, truck, refridgerator, whatever) and I'll put your picture on a page that chronicles our adventures sifting through the rubble."<br />
<br />
=== openEyes ===<br />
openEyes is an open-source open-hardware toolkit for low-cost real-time eye tracking.<br />
See [http://hcvl.hci.iastate.edu/cgi-bin/openEyes.cgi the OpenEyes hardware and software] and [http://hcvl.hci.iastate.edu/cgi-bin/openEyeswiki/index.cgi the openEyes wiki].<br />
<br />
=== RepRap ===<br />
RepRap is an open source project to create a 3d printer or fabber machine. There is tons of information available on [http://www.reprap.org its website]. The current iteration is a 3 axis cartesian robot with 2 extruder heads: a Thermoplastic head that extrudes plastics like HDPE, ABS, and CAPA, and a support material head that extrudes a water soluble material to support the build process.<br />
<br />
=== TwentyDollarWikiDevice ===<br />
<br />
Challenge: Build a Wiki Device with a parts cost of no more than twenty dollars which is usable as a portable wiki. Include feature to make it compatible with a desktop or laptop computer's PersonalWiki, with a connector allowing this use.<br />
--<br />
http://c2.com/cgi/wiki?TwentyDollarWikiDevice<br />
<br />
=== [[breakout boards]] ===<br />
These are three boards that I designed for a specific project and found them very useful. Each of these boards uses the phoenix contact plugable terminal blocks. The 50-pin breakout board is for a 50-pin ribbon cable. The LEM breakout board is for LEM AC/DC current sensor. The power supply breakout board is for a +5v +/-15v power supply.<br />
<br />
=== [[Linuxstamp]] ===<br />
The linuxstamp is an open source processor module. It is designed to be a very simple board capable of running linux. It is based on the Atmel AT91RM9200 processor (An ARM9 processor with a MMU).<br />
<br />
=== [[Linuxstamp Mboard 1]] ===<br />
This is the first mother board for the linuxstamp. It is still in the planning stages (no pcbs).<br />
<br />
=== Free Telephony Project ===<br />
<br />
[http://www.rowetel.com/ucasterisk Free Telephony Project]<br />
<br />
* Embedded Asterisk IP-PBX hardware and software<br />
<br />
* Low cost, completely open IP-PBX hardware including FXS/FXO analog and E1/T1 interfaces, and DSP motherboard hardware. Target price of $100 for a 4 port IP-PBX.<br />
<br />
== eyes for open robot ==<br />
<br />
* [http://www.sparkfun.com/commerce/product_info.php?products_id=637 $20 CMOS Camera Module - 640x480] has a [http://forum.sparkfun.com/viewtopic.php?t=2442 "Get-that-camera-working competition" discussion forum] and [http://www.makezine.com/blog/archive/2007/01/hack_this_cmos.html now been adequately documented] ... http://elinux.org/wiki/SparkfunCamera ... [http://forum.sparkfun.com/viewtopic.php?t=2442&postdays=0&postorder=asc&start=135 by David Carne].<br />
<br />
* ... perhaps simpler to use an off-the-shelf webcam that plugs directly into a laptop ... [http://www.linux.com/howtos/Webcam-HOWTO/hardware.shtml Enabling Support for Your (Webcam) Hardware in Linux] ... [http://www.saillard.org/linux/pwc/ Philips USB Webcam Driver for Linux] ... [http://qce-ga.sourceforge.net/ QuickCam] ...<br />
<br />
''Is there a simple way for my Java application to fetch the latest camera image in an Array of pixel values?''<br />
<br />
== RCAP: R/C Auto Pilot: Remote Control Auto Pilot ==<br />
<br />
"The RCAP2 is a Remote Control AutoPilot] for model airplanes, cars and boats. The autopilot function can be switched off or on during flight with the flick of a switch." Uses PIC16F876A to:<br />
* read (servo) commands from the RC server<br />
* read (RS-232) GPS location from a NMEA capable GPS (with programmable goto/waypoints functions)<br />
* drive (servo) commands to the rudder.<br />
<br />
[http://en.wikibooks.org/wiki/RCAP RCAP Documentation at Wikibooks ],<br />
and [http://rcpilot.sourceforge.net/modules/rcap/index.php RCAP PCB layout at Sourceforge ].<br />
<br />
== [http://www.remember.ro/scripts/wiegand.php Wiegand reader simple controller] ==<br />
<br />
The PICmicro 16F628 decodes [http://en.wikipedia.org/wiki/Wiegand_protocol Wiegand protocol] coming from card reader.<br />
If the card matches one of the 40 cards in EEPROM, it turns on the light (opens the door).<br />
Schematic and source code published under GNU terms.<br />
<br />
== [http://www.rcrowley.com/ComClone/default.htm ComClone2 Intercom] ==<br />
<br />
ComClone2 is a DIY clone of the industry-standard "party line" production intercom system as first introduced by Clearcom and now sourced by many other vendors. This intercom system is widely used in both live show(theatrical, music, etc.) and video production. Website provides complete construction information including PC board, etc.<br />
<br />
== [[Ethernet Module]] ==<br />
<br />
Mainly working with for 8/16 bits MCU<br />
<br />
== other lists of semi-open projects ==<br />
<br />
=== [[WikiNode]] ===<br />
The WikiNode project tries to link every wiki in the world together.<br />
Our "[[WikiNode]]" links to closely-related wiki (and their WikiNode links back).<br />
<br />
If you want to talk about something that is not quite on-topic here at Open Circuits<br />
(say, "desktop PC case modding", or "embedded Linux programming"), our WikiNode helps you find another wiki where people love to talk about that exact topic.<br />
The corresponding WikiNode on each of those wiki helps people who want to talk about "open hardware" to discover this wiki.<br />
<br />
* Are [http://positron.org/projects/ the Positron projects] "open" enough to be mentioned? I especially liked the [http://positron.org/projects/acrylic_cases/ "Lasercut Acrylic Casebuilding Tutorial" ].<br />
<br />
* Is [http://wiki.vislab.usyd.edu.au/moinwiki/PuckControl/BuildingThePuck the Vislab puck] suitable for this list?<br />
<br />
* [http://massmind.org/techref/piclist/pcbcontest.htm PICList & JAL_List free PCB contest] "this will encourage people to publish designs and get more good ideas out into the real world for everyone to see." (So, are these "open" circuits?)<br />
<br />
* http://ePanorama.net/ has a bunch of schematics and a web discussion forum. Are they "open" enough to mention here?<br />
<br />
* "Yet Another One-hand Keyboard" ( http://chordite.com/ ) "The firmware included in the download lets an Atmel AVR '2313 microcontroller interpret chords and talk to a PS/2 port." -- it's not completely open, but the license allows you to immediately download, for free, lots of technical information and a license to build up to 5 of your own. Building more than 5 requires some sort of payment to license the patent on the hardware configuration. (The software appears to be open source). There seems to be an associated Yahoo mailing list. What is an appropriate way to invite John W. McKown and others on the mailing list to use a wiki such as Open Circuits to maintain a FAQ?<br />
<br />
* [http://www.solorb.com/elect/ FC's Electronic Circuits] ?<br />
<br />
[[Category:Projects]]</div>Yanhttp://www.opencircuits.com/index.php?title=RS232_RS485_USB_Converter_Board&diff=2906RS232 RS485 USB Converter Board2007-03-06T05:06:46Z<p>Yan: /* Circuit and PCB */ updated path</p>
<hr />
<div>==Features==<br />
<!--<graphviz><br />
digraph blks_conn {<br />
mcu [shape=box, label="mcu"];<br />
RS232 [shape=box, label="rs232"];<br />
rs485_422 [shape=box, label="rs485/422"];<br />
usb [shape=box, label="slave usb"];<br />
comm [shape=box, label="common wires"];<br />
mcu -> comm [dir = both];<br />
comm -> RS232 [dir = both];<br />
comm -> rs485_422 [dir = both];<br />
comm -> usb [dir = both];<br />
}<br />
</graphviz>--><br />
*for low traffic and low speed application<br />
*mcu, RS232, RS485/RS422, slave usb all can be interchangeable.<br />
*usb side<br />
**support platform in linux with usb driver<br />
**simulated uart programming in application level<br />
*rs232 to rs485 side<br />
**Tested max. baudrate is 115200(i assume more high baudrate can be accepted, but i have not tested)<br />
<br />
<br />
==Technical==<br />
<br />
<br />
===RS232===<br />
*[http://www.realhamradio.com/tac32-interface.htm RS232 Circuit examples]<br />
<br />
<br />
===USB===<br />
*Host Computer Setting for usb connection<br />
**[http://www.ftdichip.com/ Using Solution from FTDI Chips]<br />
**[http://www.ftdichip.com/Drivers/FT2232CDrivers.htm#VCP Linux USB Driver and its usb api, a simulate uart api match to usb api FOR ftdichip]<br />
**References<br />
***[http://www.beyondlogic.org/usb/ftdi.htm beyondlogic for ftdi]<br />
***[http://ftdi-usb-sio.sourceforge.net/ sourceforge usb driver for ftdi]<br />
*chips<br />
**[http://chungyan5.no-ip.org/WebServerDocs/open_data/KnowledgeDb/ComputerSysDevelopment/apps/comm/converter/ds2232c_15.pdf ds2232c]<br />
<br />
<br />
===RS485===<br />
*chips<br />
**Linear Technology Corp., LTC2859 and LTC2861<br />
**[http://chungyan5.no-ip.org/WebServerDocs/open_data/KnowledgeDb/ComputerSysDevelopment/apps/comm/converter/DS3695.pdf DS3695]<br />
<br />
<br />
===Circuit and PCB===<br />
*[http://chungyan5.no-ip.org/viewvc/converter/ gEDA Project Files]<br />
:OR [[Media:Converter.zip|Download here, not always updated]]<br />
:gEDA libraries can be download [http://www.opencircuits.com/PCB_Footprints here] or [http://chungyan5.no-ip.org/WebServerDocs/open_data/KnowledgeDb/ComputerSysDevelopment/apps/eda/gEDA/available_library/ more updated], then modify the gafrc inside converter/<br />
*We have components and PCB, Or some have already soldered, if needed email to us: [mailto:yan@amonics.com yan]<br />
<br />
==ToDo==<br />
*get a usb chips to uart, which with linux driver<br />
**MCT P87C52UBAA(http://pfranc.com/usb/usb.mhtml)<br />
**cypress, PSoC with USB<br />
*linux driver<br />
**driver in linux : http://ftdi-usb-sio.sourceforge.net/<br />
**usb in linux guide : http://www.linux-usb.org/USB-guide/book1.html</div>Yanhttp://www.opencircuits.com/index.php?title=User_talk:DavidCary&diff=2501User talk:DavidCary2006-12-29T04:43:32Z<p>Yan: a talk through Wiki Howto</p>
<hr />
<div>Why don't you help finish my programmable chip eeg project and then use what you learned and the results to then create your own project. Programmers like to reuse working modulas instead of reinventing the wheel.<br />
<br />
<br />
<br />
==a talk through Wiki Howto==<br />
Hi DavidCary<br />
<br>Thank you very much you create this wiki to let us to share electronic projects. <br />
<br>I want to merge the "RS232 Dev Board" and "RS232 RS485 USB Converter Board", so want to discuss to the author, Tkb, of "RS232 Dev Board". However, i cannot find out the talk page like i talk to you by this way. Can you point me how to do it?<br />
<br>thanks<br />
<br>yan</div>Yanhttp://www.opencircuits.com/index.php?title=RS232_RS485_USB_Converter_Board&diff=2437RS232 RS485 USB Converter Board2006-12-16T05:51:01Z<p>Yan: /* Circuit and PCB */ updated the geda lib. link</p>
<hr />
<div>==Features==<br />
<!--<graphviz><br />
digraph blks_conn {<br />
mcu [shape=box, label="mcu"];<br />
RS232 [shape=box, label="rs232"];<br />
rs485_422 [shape=box, label="rs485/422"];<br />
usb [shape=box, label="slave usb"];<br />
comm [shape=box, label="common wires"];<br />
mcu -> comm [dir = both];<br />
comm -> RS232 [dir = both];<br />
comm -> rs485_422 [dir = both];<br />
comm -> usb [dir = both];<br />
}<br />
</graphviz>--><br />
*for low traffic and low speed application<br />
*mcu, RS232, RS485/RS422, slave usb all can be interchangeable.<br />
*usb side<br />
**support platform in linux with usb driver<br />
**simulated uart programming in application level<br />
*rs232 to rs485 side<br />
**Tested max. baudrate is 115200(i assume more high baudrate can be accepted, but i have not tested)<br />
<br />
<br />
==Technical==<br />
<br />
<br />
===RS232===<br />
*[http://www.realhamradio.com/tac32-interface.htm RS232 Circuit examples]<br />
<br />
<br />
===USB===<br />
*Host Computer Setting for usb connection<br />
**[http://www.ftdichip.com/ Using Solution from FTDI Chips]<br />
**[http://www.ftdichip.com/Drivers/FT2232CDrivers.htm#VCP Linux USB Driver and its usb api, a simulate uart api match to usb api FOR ftdichip]<br />
**References<br />
***[http://www.beyondlogic.org/usb/ftdi.htm beyondlogic for ftdi]<br />
***[http://ftdi-usb-sio.sourceforge.net/ sourceforge usb driver for ftdi]<br />
*chips<br />
**[http://chungyan5.no-ip.org/WebServerDocs/open_data/KnowledgeDb/ComputerSysDevelopment/apps/comm/converter/ds2232c_15.pdf ds2232c]<br />
<br />
<br />
===RS485===<br />
*chips<br />
**Linear Technology Corp., LTC2859 and LTC2861<br />
**[http://chungyan5.no-ip.org/WebServerDocs/open_data/KnowledgeDb/ComputerSysDevelopment/apps/comm/converter/DS3695.pdf DS3695]<br />
<br />
<br />
===Circuit and PCB===<br />
*[http://chungyan5.no-ip.org/svn/open_svn/converter gEDA Project Files], for example:<br />
:<pre><nowiki><br />
svn checkout http://chungyan5.no-ip.org/svn/open_svn/converter/trunk<br />
</nowiki></pre><br />
:OR [[Media:Converter.zip|Download here]]<br />
:gEDA libraries can be download [http://www.opencircuits.com/PCB_Footprints here], then modify the gafrc inside converter/<br />
*We have components and PCB, Or some have already soldered, if needed email to us: [mailto:yan@amonics.com yan]<br />
<br />
==ToDo==<br />
*get a usb chips to uart, which with linux driver<br />
**MCT P87C52UBAA(http://pfranc.com/usb/usb.mhtml)<br />
**cypress, PSoC with USB<br />
*linux driver<br />
**driver in linux : http://ftdi-usb-sio.sourceforge.net/<br />
**usb in linux guide : http://www.linux-usb.org/USB-guide/book1.html</div>Yan