Category: "Informative"

Intro to finite state machines (FSM)

07/04/11 | by Jfkfhhfj | Categories: Informative, General, Code

I've been out of the game of writing blog posts for a while now, but i promise its only because I've been working on some cool stuff. I'm going to be making a few posts on simple concepts before i roll out some larger projects I've been working on.

Finite State Machines:
A very important part of digital/software design is being able to control how a piece of software "flows", how the user interacts the software and how it behaves to certain stimuli. Finite State Machines associate actions (things your software/hardware does) with a current state and an input combination (Mealy State Machine) or just the current state alone (Moore Machine).

Finite state machines involve breaking your problem down into states, in which each state; the possible inputs to your code produce different results. Its a very simple paradigm, but its often hard to abstract, so we'll start with an example.

An Example:
Lets say we have a digital clock, and we have 3 buttons, there are several features we'd like to implement. Lets say for now, we can only set the time, the alarm time and turn on and off the alarm. If we list all the possible actions we find we can:

-Turn on and off the alarm
-Change the hours of the alarm
-Change the minutes of the alarm
-Change the hours of the actual time
-Change the minutes of the actual time
-So and and so forth.

So now we can do several things; one thing we can do is to have a button for every action. This really tends to eat up hardware and makes the end result sloppy and very user unfriendly (imagine having a button for every aspect of the operation of a more complicated device) Plus we stated above, we only have 3 buttons!

A much better example is to use a finite state machine, in which each button will have a different function dependent on the state that it is in.

For simplicity sake, we will be implementing the design as a Mealy machine (where the action is determined by the inputs and current state.

State Diagrams:
A state diagram is a way of representing the states that a system can take, for our clock we have Three:

State 1: The idle state, in this state we simply keep time, the user can enter programming mode from here or turn on and off the alarm

Button 1 - Will turn on or off the alarm
Button 2 - Enters programming mode (goes to state 2)
Button 3 - Does nothing

State 2: Programming mode for clock/alarm HOURS setting

Button 1 - Does nothing
Button 2 - Sets the current HOURS setting (goes to state 3)
Button 2 - Increments the set value

State 3: Programming mode for clock/alarm MINUTES Setting

Button 1 - Does nothing
Button 2 - Sets the current MINUTES setting (goes back into run mode after)
Button 3 - Increments the set values

So here, we implemented all the functions we wanted to do, with the buttons we had, and we even had ability to add extra functionality to each state!

Here is the state diagram for such a system:

Why FSM:
Besides for making hardware much more simple, FSM also has some major code benefits. The most major is now we can abstract our design into actions. We assign actions to a state/input combination and call this action when the criteria is met, with this we can break down out code and avoid "spaghetti code." This allows us to segment our code into different parts, making things easier to work on in the long run. FSM also allows us to avoid duplicate code, for example, with our clock, we have to increment the minutes and the hours, with this FSM we can write one routine to increment a register and have the current state determine what register to increment. Here we use the current state as a parameter to avoid having two routines for one thing(a simple example). There are many benefits to using FSM in your code, below i included a FSM routine for PIC microcontrollers using lookup tables. The same routine can be written with ROM tables as well.

Some Code:
Below I've written very simple code for a PIC18F micro which allows you to implement a Mealy FSM into your design. It's very simple code and is completely stand-alone, so you can implement it into any project you wish!

cblock 0x00
	INPUT
	CURRENTSTATE
	NEXTSTATE
	TEMP
endc

org 0x00
 
PORTS:
;;;;;;;;;;;;;;;;;;;;;;;
;SETUP STUFF GOES HERE;
;;;;;;;;;;;;;;;;;;;;;;;
	

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;MAIN                             ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
INIT:
	movlw		0x00
	movwf		CURRENTSTATE
	movwf		NEXTSTATE      ;Initialize States to idle

	
MAIN_LOOP:
	call		FSM
        goto        MAIN_LOOP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;This is the main FSM Code           ;
;INPUT must be from 0-256            ;               
;Each state calls the INPUT numbered ;
;Action from the lookup table        ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
FSM:
	rlncf 		CURRENTSTATE,w
	call		GETSTATE
	movff		NEXTSTATE,CURRENTSTATE
	return

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Lookup Tables
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GETSTATE:
	movff		PCL,TEMP
	addwf 		PCL
	goto		STATE0
	goto		STATE1
	goto		STATE2
	return
STATE0:
	rlncf       INPUT,w
	movff		PCL,TEMP	;Pics are stupid
	addwf		PCL
	goto		ACTION0
	goto		ACTION1
	goto		ACTION2
	goto		ACTION3
	return
STATE1:
	rlncf       INPUT,w
	movff		PCL,TEMP	;Pics are stupid
	addwf		PCL
	goto		ACTION0
	goto		ACTION1
	goto		ACTION2
	goto		ACTION3
	return
STATE2:
	rlncf       INPUT,w
	movff		PCL,TEMP	;Pics are stupid
	addwf		PCL
	goto		ACTION0
	goto		ACTION1
	goto		ACTION2
	goto		ACTION3
	return

;State actions
ACTION0:
	movlw 0x01
	movwf NEXTSTATE
	return
ACTION1:
	movlw 0x02
	movwf NEXTSTATE
	return
ACTION2:
	movlw 0x03
	movwf NEXTSTATE
	return
ACTION3:
	movlw 0x00
	movwf NEXTSTATE
	return
end

Code Explanation:
Essentially, we have three system variables, NEXTSTATE, PRESENTSTATE and INPUT, when we call FSM the program uses PRESENTSTATE as an offset for a look-up table, calling the current set state. Once a state is loaded, we use INPUT as a offset for the action associated with a state. Thus we get an action that is associated with an input/state combination.

The major downside to this code is that STATE and INPUT MUST BE FORMATTED! If they are not, you will get erratic program behavior. (I.e. if there is 3 states, the first must be equivalent to 0x00, second, 0x01, and third 0x02, same for input)

This code can also be used with interrupts as well.

 

The Great Microcontroller Showdown '10

12/28/10 | by Jfkfhhfj | Categories: Informative, Tips

Micro’s come in many shapes and sizes nowadays, what was once very simple and specialized comes in all sorts of packages with all sorts of peripherals and features. Over the year I’ve put together a healthy collection of many different platforms and devices and I’d like to share my experiences with all of them. I do not claim to be an expert of all the controller lines below, I work mostly with PIC and have a good amount of experience with AVR,I also work mostly in assembly and do little high level programming. However, I still have done plenty of research and I hope I can offer advice that helps.

The way i'm going to do this review is go over several important categories when choosing a controller, generally I see this as most important to least, however some things are interchangeable depending on the target audience and device.

Support
What type of support do outside communities offer/how good are manufacture documents
Programmers (including emulation)
How easy is it to get your code on your chip and to make sure it works.
IDE(s)
How easy is it to write your code.
Languages (including assembly and high level)
What the hell are you writing.
Cost
How big of a loan will you have to take to finish your death bot of doom.

General architectural things will be discussed throughout the review as well in non particular order. (I.e. I will be going on rants and diversions)

With all that said, let the games begin!


Microchip PIC

The first series i will be going over is my favorite. Microcontroller’s Pic architecture is very intuitive and great for hobbyists. It’s a very minimalistic approach to microcontrollers. Everything about a PIC is simplistic, the assembly, the programing, and the IDE. There is very little which is a hassle to do. For beginners, I always recommend PICs since i feel they’re the easiest chip to get started with. The PIC comes in many different varieties including the PIC10, PIC12, PIC16, PIC18,PIC24, PIC32 and DSPpic. The most commonly used lines are the PIC16, mid end 8 bit processor and their flagship PIC18 high end series microprocessor.

Support:
Microchip has always been about the hobbyists, they offer great support and they have tons of great documentation. I personally feel their data sheets are some of the best. Always well organized and very well written. They always supply good code examples in both c and assembly so you spend less time trying to interpret what they’re saying and more time programming.

Programmers:
By far the PICKIT is the best programmer available. It will program all of microchip’s products without hassle, has on board power source, its USB and very portable. Also the pickit supports debug features.

IDE:

There is something really nice about MPLAB, it’s a small download, and it works, very well. It’s a very bare bones ide, but it gets the job done extremely well. Everything is intuitive and whether you’re managing a huge project or writing a small assembly code. MPLAB just works. Simulation is a breeze as well; MPSIM works great and has everything you could ask for. The biggest gripe with MPLAB is that it is rather old and some ancient features will come back to haunt you. For a while if you weren't building in a project file path lengths had to be kept under a certain number of characters, this wasn't fixed until recently.

Languages:
Microchip’s assembly is very minimalistic, on most lines it doesn’t support fancy indirect calling, or software controllable stacks or sometimes even branch instructions(PIC16 has no branch), but for what it’s worth, Microchip’s assembly once again just works. It’s very intuitive as far as assembly goes. Although most people hate the idea of a working register I feel it defiantly simplifies things since we can address all SRAM with it. (no specialized move instructions). Interrupts are simple since there’s only one or two vectors. Indirect referencing is done via a INDF register and a FSR register (one hold the memory address, other holds the contents). Higher level series such as the PIC18’s have indirect referencing to program memory through table instructions but they can be cumbersome. The biggest downsides to PICs are the segmented memory banks. Although on the PIC18’s this isn’t much of an issue when you write small programs,on larger projects it can be a real pain in the butt.
Again I’ve done little programming with C, but microchip offers a limited C compiler for most of their micro lines. As far from what I’ve seen, it works and it’s C, what more could you ask for?

Cost:
Microchip is great when it comes to cost, if you’re a student they offer a hefty discount on their programmers and will send you free chips through their sample programs. Otherwise prices are pretty standard.

Links:
http://microchip.com/ - Microchip's Home Page
http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en019469&part=SW007002 - MPLAB download link
http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en023112 - Sample device page
http://www.microchip.com/samples/ - Link to sample program
http://www.microchipdirect.com/ProductSearch.aspx?Keywords=PG164130 - Pickit 3 programmer

ATMEL AVR

AVR is an industry standard microcontroller and regarded as one of the best. If you want simply the most powerful microcontroller in terms of functionality, AVR is for you.

Support:
Atmel’s support is second to none; if you can manage their website you will find documentation on everything. These guys have some of the technically best datasheets out there. With that said, technically best isn’t always the best. Their datasheets can be a chore to read through at times, but you defiantly get the full picture. Also unlike microchip whom include all their supplementary data in their device datasheet, things like instruction set summaries are supplement documentation and you usually have to hunt them down. (That’s what Google is for). AVR also has generally pretty large communities behind them (*cough* AVRfreaks *cough*) As well, they’re the go to micro in industry and university.

Programmers:
*bangs head on desk* the most frustrating aspect of any AVR chip is programming the damn thing.
There is no one programmer from ATMEL that will program all their chips. Some use ISP some use JTAG some use god knows what. The best thing to do usually is grab a JTAG programmer off of ebay and stick to an ATMEGA series chip. Most AVR microcontrollers support several programming options, this is nice however can bit a bit confusing at time (see above :P). The most common interface is ISP which is your standard In-Circuit Serial Programming.AVRs also support JTAG and other high voltage serial/parallel programming algorithms.(check out the data sheets) You can buy the 40$ AVR Mkii ISP and be able to program most if not all of their stuff. Programming through ISP can be a nightmare especially if you set the wrong fuses and brick your chip (very easy to do). Also ISP is very finicky with the programming speed and sometimes doesn’t work. I’ve even had issues with JTAG. Many times if the proper power up sequence isn’t followed the chip will refuse to talk to the programmer. This is by far the worst experience with AVRs but once you figure out the kinks of whatever setup you have, it’s usually smooth sailing (until you F$*#K up the fuses).

IDE:

AVR study hands down is one of the sexiest worksuites available for a micro. It’s just sooo shiny. And then it crashes. But really, AVR Studio is a great IDE and it’s the complete opposite of MPAB IDE. It’s a bit of a PIA to download and update (requires registration and multiple service packs) but it’s a fully featured modern IDE. One of the biggest problems with MPLAB is how ancient it feels and looks, with AVR Studio this is not an issue. As an IDE it does everything you could want it to do, everything is intuitive and when emulating there are just some really nice features that blow any other IDE out of the water. It’s a great IDE, just wish they would iron out some of the bugs.

Languages:
AVR assembly is both its greatest strength and weakness. In terms of sheer power, the AVR assembler is unmatched and the language is almost flawless. However, there is a steep learning curve associated with AVR and it’s assembly language. This mostly has to do with how it’s memory is arranged and mapped.

AVR memory:
Like all processors we have our CPU, Ram and Rom. In an AVR our program memory is 16 bit long and that constitutes our word length, this program Rom is accessible through our Z pointer. (and our LPM and SPM instructions). We can use program memory to both store instructions as well as ROM lookup tables. By using the .db(Define byte) and .dw(Define Word) we can load Rom with values at assemble time. This is mostly due to the power of the AVR assembler and ability of the Z pointer to indirectly reference program memory. This is an extremely useful feature.
Now the AVR RAM is a bit peculiar. The SRAM is mapped linearly and broken up into sub blocks. We have a General Purpose Register (r0,r31), I/O space (Our IO ports and Special function Registers) and our Data SRAM (everything else). Data SRAM is where we hold our system variables and where the stack pointer resides. Another really powerful aspect is that with AVRs we can use our PUSH and POP instructions to load the stack with system variables as well as control program flow.
However there is a downside to this implementation. Depending what sub block we are addressing, determines which instructions we use. We can generally address any space with our GPRs, however if were loading to IO space we use the in and out instructions, and if we load to data space we use lds and sts. Moving between GPR is done via mov. If you program a lot with AVR, this actually isn’t too bad, and preferred in some cases (prevents data corruption). However, it’s all a gimmick. The memory space is completely linear, there is no reason you can use an out instruction to load to a GPR to data space, it’s the same memory and in some cases you can(play around with it its fun)! The only thing preventing you most of the time is the assembler itself. Because of all these different instructions to do the same thing it can get rather confusing (SBIS, SBRS). For beginners, I do not prefer AVR assembly and I think at times it can be really counter intuitive.
With a PIC, the memory space is linear. Although we have a working register W0, there is only one Mov instruction (From and To W.) which addresses all RAM.
With that said, AVR assembly is great if you know what you’re doing, it’s extremely powerful especially with things such as software stack and its indirect referencing system, but for novices it can bit a bit much.
C, is a completely different story. One way which AVR blows microchip out of the water is through its C compiler and general C support. Out of the box AVR studio works with C and uses a GCC compiler so for those Linux guys they’re covered as well. This is where Microchip could learn from ATMEL.

Cost:

Here is another gripe I have with AVR’s. And it mostly goes back to programmers. There really is no one programmer that does it all, and because of this the costs associated with developing with AVR chips can be quite high. If you use the ATtiny line, you need an ISP programmer if you use ATmega you need a JTAG programmer and if you use anything else, well good luck. Although programmers can be chopped together easily, it’s nice to be able to buy something from the company that you know works (Instead of relying on Chinese clones). Also ATMEL’s sample program is almost nonexistent, you gotta buy all the chips you use, So no love for students.

With that aside, the costs aren’t tremendous, you can get an ISP programmer for around 40$, and the chips themselves are never more than a few dollars. However I wish ATMEL made more of an initiative to make things a little bit friendlier.

Links:
http://www.atmel.com/ - Main website
http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&name=ATAVRISP2-ND - AVR ISP Mkii programmer (for ATtiny Chips)
http://www.atmel.com/dyn/products/product_card.asp?PN=ATmega48 - Sample product page
http://www.atmel.com/dyn/products/param_table.asp?family_id=607&OrderBy=part_no&Direction=ASC List of all their products and features.

*This concludes the part of the article of the chips I actually know a bit about, please only use the following for reference*

TI Launchpad MSP430

This is TI’s attempt at getting back into the minds of hobbyists. This line is meant to be cheap affordable and no frills. The actual processor is built around a simple but powerful assembly language and has very barebones peripherals. TI released an evaluation kit for the MSP430 called the Lanuchpad which main feature is that it only costs 4.30$ and includes theoretically everything you need to get started.

Support:
There seems to be a good amount of support documentation floating around, and TI does a decent job of providing a good amount of documentation. Ti is really trying to make a push into the hobbyist market and offers a wiki for their launchpad product.

Programmers:
Programming depends on the device but for the value line, programming seems to be done via a serial interface. The launchpad evaluation board has a programmer and emulator onboard, so that should be all you need to get going. It will also program other MSP430 devices and not just the value line.

IDEs:

TI provides a link to IAR embedded workbench, which works, most of the time. It’s a decent toolsuite, but doesn’t hold a candle to dedicated suites such as MPLAB or AVR studio. (and it just crashed on me... $*$#@!!!)

Languages:
I haven’t had much time to play with the assembly, but from what I see, it truly looks very “modern.” We have a very small instruction set, but we also have some really powerful assembler directives that allow control of the stack and the ability to easily create ROM tables. It’s the best of both worlds. It’s a really nice step in the right direction with a nice core.

Cost:
4.30$, its cheap and for that it’s worth it in parts alone, if you can get an IDE to work with it, it’s a great chip which has a lot of potential.

Links:
http://processors.wiki.ti.com/index.php/MSP430_LaunchPad_%28MSP-EXP430G2%29?DCMP=launchpad&HQS=Other+OT+launchpadwiki - Launchpad Wiki
https://estore.ti.com/MSP-EXP430G2-MSP430-LaunchPad-Value-Line-Development-kit-P2031.aspx - Buy it
http://focus.ti.com/lit/ds/symlink/msp430g2211.pdf - Datasheet for value line chip

Parallax Propeller

This is quite possibly one of the most interesting processors I’ve ever come across. Parallax builds its processors around “Cogs” or miniature processor cores. Each processor has its own peripherals, shares IO and has access to main memory in a round robin fashion. A typical propeller has 8 cogs which can run at an impressive 20 MIPS, giving you a total of 160MIPS per chip. I’ve found that this chip is defiantly nice and very impressive especially coming from such a small company like Parallax, but I still have a hard time seeing exactly what its really good at. It seems the processor is much geared mostly towards game development (each core has its own video genorator).
There are also a few quirks you should be aware of. First off, there is no rom, so all programs are run off of the ram. Unless you have external EEPROM, every time you reset the chip your program is lost. Part of the startup routine includes looking for external EEPROM and automatically loading its contents into RAM. Another quirk is all the IO is shared via each processor core, not only that, IO control is OR’d with each COG, so things can get pretty messy. Really, you have to check out the documentation for this chip because it is very interesting.

Support:
Parallax is a very small company but their effort is the same as any other large companies. Their datasheet’s are pretty informative and they have just the same documentation you come to expect. Their website is pretty informative and easy to navigate and it’s a breeze getting everything you need to get up and going. However i've yet to find any real support online like there is for the other processor cores mentioned.

Programmers:
Programming of a propeller is done via serial and you can use any USB to serial adapter to do this. The one provided on their website is incredibly cheap and nice and compact. Because of the onboard bootloader, things are pretty no frills here.

IDE:

You can download the free Propellor Tool from Parralax’s website. This is a super simple IDE, again no frills, just what you need to get things working. The best thing about Propellor Tool is the sheer amount of reference code that comes with the IDE. You’ll have plenty of examples for both the SPIN language and assembly. Once you can figure out what you’ll use your chip for, you’ll have no lack of reference code to tear apart.

Languages:
The assembly is pretty standard and does everything you expect it to do however programming for a multicore chip is rather, interesting. Essentially each cog has its own RAM to store its program, while the main system RAM holds your main program. Using a SPIN command you can enable a new processor and you set the origin address of the assembly you would like it to load. On startup, the cog will take that code from the main memory and dump it into its ram. This usually takes a little while but allows each cog to independently run its own code.
If you don’t feel like dealing with that, you can use the high level SPIN language which is a combination of C, BASIC and some really interesting preprocessor directives. I haven’t used it much but you can do some really powerful stuff pretty easily. One of the interesting things is this processor support direct driving of a composite video signal and has instructions to generate text to any NTSC TV set. Pretty cool stuff for a little micro.

Cost:
The propeller is defiantly an expensive chip, but you’ll only need one and the chip is pretty much all you need to get going. If you want to grab a chip “programmer” and eeprom from parallax it’ll run you about 20$ shipped, which isn’t bad at all. So it’s an expensive chip, but that’s only because of the sheer amount of stuff you get in that little hunk of silicon.
Links:
http://www.parallax.com/ - Parallax main site.
http://www.parallax.com/propeller/ - General Information for the propeller
http://www.parallax.com/Store/Microcontrollers/PropellerChips/tabid/142/ProductID/332/List/1/Default.aspx?SortField=ProductName,ProductName - Buy a Propellor here
http://www.parallax.com/Store/Microcontrollers/PropellerTools/tabid/143/List/1/ProductID/398/Default.aspx?SortField=ProductName%2cProductName - Programmer here
http://www.parallax.com/Portals/0/Downloads/docs/prod/prop/WebPM-v1.1.pdf - Datasheet here

Arduino

Ardunino is a hit with the hobbyist community. Combine open source, with tons of support, tons of code, high level language and a super simple interface and Arduino is what you get. Arduino Is essentially a bootlaoder for the popular ATmega series of chips made by ATMEL. Arduino is nothing more than a wrap for AVR chips and a philosophy, provide the support and the hackers will come.
However, there is a dark side to Arduino, with the simplicity a high level language offers, it also brings forth hacktronics and some pretty shoddy engineering. If you’re someone with little electronics experience and you want something cool to play with, Arduino is for you. If you’re an EE who wants to learn microcontrollers I recommend Arduino AFTER you learn a more substantial core. Then you can use Arduino as a powerful development tool and not as a crippling toy. (Seriously what did you expect from someone who prefers assembly over C?)

Support:
Go on any major hobbyist website/hacker community and if you can’t find support for Ardunio you’re doing something wrong. Unlike the corporate driven datasheets and reference documents you will find hacker guides and tons of support from people who just love to hack. The Arduino website is chock full of information as well. This is the beauty of open source, the wealth of information.

Programmers:
Arduino is programmed via USB and usually when you get your Ardunio board it has a USB header on it which is all you need to upload your compiled programs.

IDE:

Arduino’s main IDE is a simple .jar program which is cross platform and extremely minimalistic. You write your sketches and compile them onto your Arduino and off you go. Nothing more is needed. Support for outside compilers is plentiful aswell. No matter what platform you run, you can program with Arduino.

Languages:
Arduino is prized for it’s C like language which is incredibly high level and very powerful. Open source libraries add everything from sound generation to image processing and everything between. Find your library, learn some simple commands and that’s all you need to get going with Arduino. If you actually care what’s going on, good luck(:P).

Cost:
A typical Arduino board will go for around 20$. Part of the Arduino philosophy is the idea of shields. Stack-able modules which connect to your main Arduino board and add features such as sensors and other peripherals. Shields can range from cheap to expensive depending on the functionality. Arduino is very affordable for anyone to jump right in and build some pretty impressive electronics.

Links:
http://www.arduino.cc/ - Main website
http://arduino.cc/en/Main/Software - Programmer
http://www.sparkfun.com/products/9950 - Arduino Uno, latest board

ARM


The holy grail of microcporcessors. These processors are in everything from your Iphone to your toaster. However you’ll never find an ARM chip. ARM simply licenses its processor core for companies to modify at their leisure. At its heart ARM is a general purpose RISC processor.

Support:
The first part of developing with ARM is finding a vendor and figuring out what support they offer. ARM platforms can range from elaborate to very simple and can be an evaluation kit or just a dip chip. Typically ARM processors interface through JTAG or serial and you upload binaries into the Rom.

Programmers:

Programming is typically done through JTAG or serial and varies from manufacturer to manufacturer (Hint, find one which works first)

IDE:
Varies from manufacture to manufacture, however anything that generates ARM binaries can be used (usually).

Languages:
Typically c is used when programming with ARM however an extensive assembly language is usually provided, I’ve yet to find an appropriate assembler.

Cost:
Developing with ARM can be a costly experience or it can be dirt cheap, it just depends on how much time you’re willing to spend banging your head against your desk and wondering why you can’t get the damn chip to work. Unfortunately, if you’re working with ARM you’re already provided with everything you need from whomever you’re working for. If you’re trying to work with ARM you have a lot of research ahead of you.
Links:
http://www.arm.com/ - main ARM website
http://mbed.org/ - Platform based around ARM Cortex m3 processor
http://en.wikipedia.org/wiki/ARM_architecture - Best source of information about ARM
http://www.st.com/internet/evalboard/product/250863.jsp - Really cheap ARM eval board.

X86
HAH!
http://www.intel.com/products/processor/manuals/
http://en.wikipedia.org/wiki/X86_assembly_language
Have fun..

So which is the best?

Honestly, there is no best, nor is there a worst. The best thing sometimes is just to pick a chip and just start working with it. What you should do is rather than pick the “best” or “easiest” chip, pick what works for you best. Also instead of learning what a chip CAN do, learn what a chip CAN’T do, because often times this is what will limit you the most. Understand a chip’s limitations so that when you come across them you know how to deal with them. In either case, happy programming!

I hope this article helped to shed light onto the subject of different processor brands out there. I know my knowledge isn’t complete so I hope anyone who would like to shed light on the caveats I skimmed over to do so. I will gladly add more processors to this list as I come across them and I look forward to updating the sections I glanced over. Even with these faults I hope this serves as a nice intro guide into the world of different processors.

Any questions comments or concerns, email me at Anthony.Tricarichi@sunysb.edu

 

Introducing the PIC18

12/22/09 | by Jfkfhhfj | Categories: Informative, General

I figured it'd be a good time to move to a more capable microcontroller as the projects on the blog seems to be getting more and more complicated and lets face it, keeping up with our PIC16 and their limitations can get a little annoying when you're moving lots of important data. We need more pins, we need more features on the chip and we need better instructions.

Enter the PIC18 series from microchip.

http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2696&param=en537796

The PIC18 is the most high end 8-bit microcontroller that microchip offers. It has many advantages over the lower end PIC16s the biggest being a new and improved instruction-set and memory management system.

I suggest you take a look at a datasheet for a PIC, everything in this article will reference:

http://ww1.microchip.com/downloads/en/DeviceDoc/39605F.pdf

A new memory system:

The coolest thing with the PIC18s is an Access Bank system. In this system the MCUs RAM is divided up into 16 banks (0-15)> Each bank has however many memory addresses(Depending on PIC, for example the PIC18F1220 has 256 byte banks) and you select which bank you want with the BSR (Bank Select Register). This sounds awfully similar to ram-pages of the PIC16F however its the access bank delimiter in the opcode that makes life so much easier. The access bank is the first 128 Bytes of bank 0 (Our General purpose registers) and the last 128 of bank 15 (Our Special Function registers) by default all operations are done in the access bank (a=0)This allows us to access a good amount of GPR and all of our SFR without ever changing what bank were working in. No more STATUS,RPx calls. However if we want to access ram outside the access bank we have to set the access bank delimiter call in the instruction to 1 and then by default you will be working in whatever bank happens to be set in the BSR.

Software accessible Stack:

I'm not too familiar with this feature, but the PIC18 allows you to control the stack from software, you also have complete control over the stack pointer, this is extremely powerful and not offered on the PIC16

New and improved modules:

The PIC18 series features an 8-bit hardware multiplier. Microchip provides sample code for doing all sorts of fun arithmetic. This is good if you want to crunch numbers but don't want to go into a full DSP. Also some PIC18s feature on chip USB and other goodies.

Priority interrupts:

This is another really cool feature. The PIC18 features two interrupt vectors, one high priority and one low priority. This allows you to have a really complex interrupt scheme allowing really sophisticated user interaction. For every interrupt you can choose what priority it is. An example of this is having a sample system for a sensor have highest priority while the user interface is low priority, that way even if the user is interacting the device to cause an interrupt, you don't interrupt the sample of the sensor if it is time sensitive.

NEW INSTRUCTIONS!:

This feature is going to take me the longest to get used to, but the PIC18 features a plethora of new instructions to make our lives easier. One nice and needed one is a MOVFF instruction (move from one register to another) These instructions are meant to speed up your code and make execution much faster. All new instructions follow a similar style to the traditional ones, they just do more for the clock. You can take a look at them on page 193 of the datasheet.

Free C compiler:

Microchip offers a free c-compiler for the PIC18 series for MPLAB, i haven't used it but its free and its a c compiler.

Tons of other stuff i still have to figure out:
I'm working on it :P

The PIC18 series is a really powerful line and there isn't much that they cant do. The first project i will be posting with them is a Digitial Audio Processor, we'll be taking advantage of the priority interrupts to make really fast and efficient code.

Hope to see you soon, happy programming!

 

The Fundamentals of Digital Audio

12/08/09 | by Jfkfhhfj | Categories: Informative, General

Digital audio is a very powerful thing, we listen to our iPods every day, we stream music from websites using our computers and we work with many algorithms derived from techniques in digital audio. Digital audio has its roots in wave mechanics and is a very fundamental process for modern computation. We will be discussing sound as a wave, some basic properties of waves and how to convert a wave into something which you can store in memory, and techniques to play that wave back. We’ll start with an introduction to sound and how to represent sound as a wave, and a mathematical function.

An introduction to sound:

Sound is a wave, and like all waves it transfers energy through a medium, in this case it is usually air. Whenever something emits a “sound” it compresses air molecules, these compressed air molecules exert a force on uncompressed ones, this starts a chain reaction and sound propagates; this is the essence of a sound wave. For sound to exist you need a medium, be it air, a solid, liquid or plasma. The sound wave will travel through that medium until it dissipates completely and is undetectable. Sound is usually the result of a force or stress on an object, you hit a tuning fork on a table, and it will vibrate at a particular frequency. To better visualize a sound wave mathematically, we will look at strign vibrations.

String Vibrations:

Like a turning fork, a string when plucked vibrates a particular frequency. The frequency at which a string vibrates at is due to its mass, length and tension on that string. The frequency which is most prevalent is called the fundamental frequency, when you play middle c on an instrument the fundamental frequency is 261 Hz. Now if middle c is a set frequency, why does middle c sound different on different instruments? The answer is because the sound from an instrument inst pure, each instrument has a unique harmonic structure which delivers a unique sound. To understand this more let’s look at the math of a wave.

Mathematical representation of a sound wave:

The nice thing about waves, is we can represent them mathematically, the simplest being that of a sine wave. Sine is a natural function which oscillates between crest to crest at a particular frequency. We can represent a pure oscillating sound by the following function.

Where A is the amplitude (sine is a function which oscillates between 1 and -1, multiplying it by A will result in A as the amplitude). The Greek letter omega is the angular frequency which is denoted in radians/second and the Greek letter phi denotes the angular offset (for all cases in this article we can consider it zeros). A “Pure” sound is that which is sinusoidal, we here these all the time on cheap synthesizers, when a sound is sinusoidal, it can be represented by the above formula alone. If a synthesizer were to play middle c, it would produce a sine wave of frequency 261Hz (omega = 640) and what you would notice is that it sounds like the right pitch, but no natural instrument sounds like a pure tone. When an instrument makes a tone, it is usually comprised of its fundamental frequency and higher order oscillations called harmonics. Harmonics are usually either ½(Strings) or ¾(Closed tube) integer multiples of the fundamental frequency of a lesser amplitude. Because of this we can consider and natural tone a superposition of fundamental sine waves and harmonic sine waves. Most tones in nature are comprised of a superposition of sine waves. We can use this fact to break down any complex sound into a series of many simple ones governed by the very simple formula above.

Synthesizer theorem:

Breaking a complex sound into a series of sine waves can be done using a Fourier series. A Fourier series simply is a mathematical series which can break apart any repeating oscillations into a series of simpler sine waves. We use a Fourier transform to translate an arbitrary function into a series of sine functions. For the purpose of this article we’ll use a Fourier series as a concept and we won’t be exploring the math behind it (Maybe one day).

To give a quick example of this we can consult Wikipedia. We all know and love our humble saw tooth wave; If we find the Fourier series of a saw tooth wave we get the following series as a result.

If we take n=1 we get the fundamental frequency of the series:

If we take the first 5 terms we get:

As we take n to infinity, we get a better and better approximation of our function. This is the fundamental way in which analog synthesizers would generate more complicated sounds, they would take several sine wave oscillators which they would combine in ways to reproduce a wave, and they wouldn’t need many because after a while the approximation was good enough to replicate the sound. This is fine and dandy, but in digital circuits we do not use sine waves as our building blocks, instead we use impulses.

The Impulse wave:

An impulse wave is completely different from a sine wave, instead of taking a wave as an infinite series of sine waves; we take the function and evaluate its value at a specific time t. We break the function up into many steps and by taking the value at every step we can reconstruct the wave. In this scenario as step size goes to infinity, we get a better reconstruction of the wave.

In this graph we have 5 impulses (red) that make up the waveform (green). Each impulse exists at time t and has a definite height to it. We break up a wave into specific impulses with definite height, we do this every sample. If the red waveform were 10KHz and we had 5 impulses per period, our sample frequency would be 50KHz. Each sample all we do is record the height of the waveform at that time.

="http://mcuplace.com/mcu/media/blogs/blog/impulse.jpg" alt="" title="" width="400" height="280" />

If we were to reconstruct the wave using our impulses we would get the following:

="http://mcuplace.com/mcu/media/blogs/blog/step.jpg" alt="" title="" width="400" height="280" />

As you can see, its not a pretty picture, but if you were to filter the signal, you would get a pretty good reconstruction of the original. To increase reconstruction we increase the sample rate and get more samples of the waveform per period. A wave with 100 samples/wave looks much more accurate than one with 10 samples/wave.

One golden rule is that your sampling frequency should always be above that of your highest recorded sound (Or at least the ones you would like to capture)

Digital Audio:

The heart of digital audio is taking an analog sound signal in the form of voltage over time and doing periodic analog to digital conversions and then storing these results in memory for later use.

Lets go back to our graph with the impulses. Lets say the vertical axis is voltage and the horizontal is time. Every impulse we sample a wave:

IMPULSE # -- VOLTAGE -- A2D(Int)(VDD=5V) -- T(uS)(@50KHz/Sample)
1         --  .1     --  5               -- 20
2         --  .2     --  10              -- 40
3         --  .3     --  15              -- 60
4         --  .4     --  21              -- 80
5         --  .5     --  26              -- 100
6         --  .1     --  5               -- 120
7         --  .2     --  10              -- 140
8         --  .3     --  15              -- 160
9         --  .4     --  21              -- 180
10        --  .5     --  26              -- 200
etc...

In all digital audio systems there are two things which determine your bandwidth.
The first is bit-rate which is how many bits you use to convert the signal. A bit-rate of 8-bits can break a signal up into 256 parts, thus a 5V signal has an ideal resolution of (5/256) 19mV(not bad!).

The second is sampling-rate, this is how often you sample a waveform, typical MP3 sample rates are about 44.1KHZ or one sample every 22uS.

The bandwidth of a signal is simply the sample-rate times the bit-rate.

The advantage of a digital system is that 22uS is rather slow, we can do a lot of work between sampling and storing a waveform, and with some good code we can produce high-quality powerful audio systems which are easy and cheap to make.

What now?
So now that we have an introduction to basic properties of sound, what can we do now? In upcoming posts i will be discussing the PIC18 series of micro-controllers, and some sample code to do audio pass-through and eventually storing and playing back a waveform.

 

Weak Pull up Resistors.

09/21/09 | by Jfkfhhfj | Categories: Informative, General

I haven't posted in a while so i figured i'd get back into the swing of things by posting a short post on the pic's internal weak pull up resistors.

What are pull up resistors?

A pull up resistor is a fairly high resistance (usually 1K for TTL and 10K for CMOS) resistor to pull a pin to a high logic level. This is very useful as this prevents your logic levels from floating between 1 and 0. This also lets to prime a pin to a certain logic level and have an event (such as a button press) be used to then pull your pin to another logic level.

You can also pull pins down to ground if you desire using the same method (except hooking the resistor between the pin and ground instead of the pin and vdd)

For the pic16f690 you can enable WPA by clearing bit 7 of OPTION_REG (cleared by default) and setting the appropriate bits in the WPUA(bank 1) and WPUB(bank 2) registers.

This feature is extremely useful in keeping more hardware inside the pic and using as little external hardware as possible.

Often you will pull up a pin to vdd and have a button press short the pin to ground (making the pin a 0) instead of having an external resistor you can just use the on-chip WPA resistors.

So, just a short write up for now, but i have plenty of stuff coming in the next coming weeks.

I would like to introduce the PIC18 line of microcontrollers and begin posing some more sophisticated tutorials.

I will also be updating the circuit blog to include some soldering advice.

Most importantly, i need suggestions and comments, if there is a guide you would like to see, please don't hesitate to ask!

I'm looking forward to the next year to bring even more exciting content to my blog!

 

PIC Memory Organization & EEPROM Control

04/01/09 | by Jfkfhhfj | Categories: Informative, General

One of the most key features of any electronic system is how memory is organized. This includes how much Ram and Rom, how they are subdivided and how to access the memory. Every series of PIC is different and every PIC has different amounts of memory. It is your job to understand how memory is mapped in your system and to use if efficiently.

A memory system defines a system, it is the one thing that makes it unique and when you master it, you master a system. This has two effects, it makes a system hard to master, and it makes other systems easier to use. Every system from X86 to PowerPC to our PICs are essentially the same thing, ROM to store program data, RAM to store variables and running code and a processor to crunch data. No matter what, a processor might have different instructions, but it still is a beast that doesn’t change too much. ROM and RAM define a system; every system is going to use it differently. The logic rarely changes system to system however the code can do a complete 360 depending on what system you use just because of how memory is mapped.

First let’s define a few things:

RAM (Random Access Memory): This is the place where your variables reside (General Purpose Registers), and how you access special function registers. When you setup a Cblock or set a variable to an address, this is where it’s going. RAM is super fast but very limited, and everything is stored temporarily. RAM is merely to hold values that are important to current operation.

ROM (Read-Only Memory): ROM is like your hard disk, its where all permanent data is stored, like your program. This is marginally slower but not too slow. Unlike your hard disk, this ROM is super fast since it’s on die. When you program your code onto a PIC this is where it goes.

Since a lot of this blog focuses on the PIC16F690 I am going to be going over the memory architecture of it.

Everything on memory organization can be found in the section 2.0 Memory Organization:
http://ww1.microchip.com/downloads/en/DeviceDoc/41262E.pdf

The first section goes over a few things you should know:

The RAM is partitioned into 4 banks (0-3). Depending on the data you’re addressing depends on which bank you need to access. In each bank you’ll find a mirage of General Purpose Registers, used for storing program variables, and Special Function Registers, used for controlling the microcontroller. The next few tables’ show where these SFR reside and what banks they’re located in. The rest is just trivial stuff we’ve gone over before.

Likewise how the RAM is partitioned so is the ROM. The ROM is compromised by Program Memory and Data Memory. Program memory is reserved for your program (however on PIC18’s and above you can write to it and use it for data). Data memory is used exclusively for storing data. On the PIC16F690 it is 256 Bytes. Writing and controlling this DATA ROM is not as straight forward as controlling a GPR.

The PIC has a built in EEPROM control module which you use to read and write to EEPROM.

The EEPROM Control Module:

This module is fairly simple and allows you to store program variables in hard data for later use. 256 Bytes doesn’t sound like much but it does come in handy.

The Registers:

EECON1: Control register.
EECON2: Non implemented register used in writing data (see below)
EEDAT: This is the register that holds the data to be written or has been read.
EEDATH: Some memory is larger than 8 bits so this is the High portion of the register that contains the MSB of a non 8-bit number.
EEADR: This is the register that holds the memory address of the a data to be read or written
EEADRH: The high register for EEADR for non 8-bit addresses.

The Sequence:

Write (Data memory only):
Configure EEPROM for write
Set the address to be written to EEADR and EEADRH
Set the data in the data registers
Initiate a write sequence and wait.

Read (Data and program memory):
Configure EEPROM for read
Set the address to be read to EEADR and EEADRH
Initiate a read sequence and wait.
Data will be in the data register.

The sequence is pretty straightforward, the only tough part is the control so lets go over EECON1.

EECON1: EEPROM control register
Bit 7: EEPGD – 1: Access Program Memory 0: Acess Data memory
Bit 6-4: Unimplemented
Bit 3: WRERR – 1: There was a write error 0: Write operation completed
Bit 2: WREN – 1: Allows write to EEPROM 0: Write is not allowed
Bit 1: WR – 1: Initiates a write 0: Write is complete
Bit 0: RD – 1: Initiates a Read 0: Read is complete.

As you can see, this module is pretty simple a sample read code will be something of the sort:

clrf  EECON1 ;Read Data memory, do not allow writes
movlw 0x00
movwf EEADR
movwf EEADRH   ;Clear address location start at 00
bsf   EECON1,0  ;Initiate read
btfsc EECON1,0  ;Wait till clear
goto  $-1
movfw EEDAT     ;Move read data to where-ever
movwf DAT

Reading from EEPROM will be very similar to the above routine just make sure you're in the right banks for each register (EECON1 and EEDAT/EEADR aren't in the same bank)

Writing to the EEPROM isn't exactly as intuitive as reading but is still pretty easy:

Just like above, you set up the EECON1 register for whatever you're doing and move the data you want to write into EEDAT and the address you want to in EEADR and EEADRH. After you do that, you initiate a write sequence such as the following:

WRITE:
	bsf      STATUS,RP0
	movlw    0x55      
	movwf    EECON2
	movlw    0xAA
	movwf    EECON2
	bsf      EECON1,WR   
	btfsc    EECON1,WR
	goto     $-1
	bcf      STATUS,RP0
	return

Now, to write to data EEPROM you must write 0x55 then 0xAA to EECON2 (one after another) and then set the WR bit on EECON1.

This sequence is what is required by Microchip in their data sheet.

Other thank that, EEPROM control is fairly straight forward and is very powerful.

Good luck and any questions/concerns please feel free to send me an EMAIL.

 

Intro to the HD44780 character based LCD

01/31/09 | by Jfkfhhfj | Categories: Informative

This post is going to go over using an HD44780 character LCD. These LCDs come in many sizes by are usually defined by how many characters they display; split by how many lines and characters per line.

The one thing about these LCDs is that they have a built in microcontroller, so we are going to be using our PIC microcontrollers to interface with the built in MCU on the HD44780 LCD.

Interfacing with the LCD is rather easy but often guides are very vague on exactly what you have to do. I will be going over how to statically and dynamically update the LCD using our PICs.

The LCDs work by first configuring how the LCD operates (usually an initializing routine you use from code to code. The way the LCD displays data is that each "character cell" corresponds to a DDRAM address (Display Data RAM) you load the ASCII Hex value into the DDRAM address and the corresponding cell displays that character. Thats it! Its pretty easy to use these LCDs.

How it works:

I would first like to post a wonderful link which i used to learn how to use these LCDs. It has all the info you need but is a little confusing if you don't know what to look for.

Link: http://home.iae.nl/users/pouweha/lcd/lcd.shtml

Any HD44780 character LCD with <=80 characters (less than or equal to) will have 16 pins. For MOST LCDs (ALWAYS consult your data sheet first)

Pin 1 is VSS(Ground)
Pin 2 is VDD(Pos voltage)
Pin 3 is Vee, or voltage for contrast adjustment you hook this up in a voltage divider configuration with a potentiometer or trimmer. You use this to adjust contrast.
Pin 4 is the RS line which controls whether your sending data or an instruction. 0 is for an instruction, 1 for data.
Pin 5 is Read/Write from/to the LCD, 0 for Write, 1 for Read.
Pin 6 is the most important, it is the Enable signal, The enable line for the HD44780 is edge triggered, on a falling edge (1->0) The HD44780 reads whatever is on the data bus. This is the one thing people have most trouble with.
Pins 7-14 is the primary data bus. Its 8 bits long and you can either hook it up to a spare 8 bit port or use serial communication and a shift register.
Pin 15 is the anode to the back light. Make sure you put correct voltage across this and the cathode
Pin 16 is the cathode to the back light.

Now that you know the pin out lets look at some instructions:

Commands:

Instructions control the operation of the LCD, They clear the DDRAM addresses, reset the address counter, set how the address counter functions, how the text displays and various other functions. We do all this before we send any data to the LCD, this initializes the LCD and gets it ready for accepting data and displaying it in a meaningful fashion.

To send an instruction we set the RS and R/W lines both low. When this happens we put the instruction we want onto our data bus and send it by setting the enable line from high to low.

The Instruction set:

Command: Clear Home
RS:0
RW:0
DB:0x01

This command clears the DDRAM and sets the address counter to 0x00

Command: Return Home
RS:0
RW:0
DB:0x02

Moves the address counter to 0x00, leaves the DDRAM untouched.

Command: Entry Mode

RS:0
RW:0
DB:0x04-0x07 (000001MS)

This controls what the cursor does when it gets a command. Bit "M" controls weather its to the left or the right. 0 will decrement the cursor position, (move it to the left) a 1 will increment the cursor position (move it to the right). S Controls if the display shifts (Where the text moves but not the cursor position) 0 is off and 1 is on.

Command: Display Control

RS:0
RW:0
DB:0x08-0x0F (00001DCB)

Sets weather the display is on(D) (useful), if the cursor is on(C) and if the cursor blinks(B). A 1 correlates to enabled.

Command: Cursor / Display shift.
RS:0
RW:0
DB:0x10-0x1F (0001SDxx)

This allows you to shift(S) the display(1) or the Cursor(0) and what direction(D) left(0), right(1)

Command: Function Set

RS:0
RW:0
DB:0x20-0x3F (001LNFxx)

Sets basic control information for the LCD

L - Data Length: 0 - 4-Bit communication (We will be using 8-bit) 1 - 8-bit communication
N - 1 line or 2 line: 0 - 1 line 1 - 2 line, (just set to 1)
F - Font: 0 - 5X7 Dots 1 - 5X10 dots. Set to 1

Command: Set CGRAM address
RS:0
RW:0
DB:0x40-0x7F (01(ADDRESS))

HD44780 LCDs support custom characters, CGRAM is where you set them, i will not be covering custom characters in this post.

Command: Set DDRAM address

RS:0
RW:0
DB:0x80-0xFF (1(ADDRESS))

This sets the DDRAM address which you will start sending data to.

Sending Command to the LCD:

To send commands to the LCD we have to do several things.
-Set the RS and RW line
-Put the data/instruction we want to send on our data port (any 8 bit port)
-Send it
To send data to the HD44780 we set the E line high, do a few NOPs and then set it low. The HD44780 reads the command and operates accordingly.

While the HD44780 is performing an operation we cannot send data to it. There are two ways we can make sure we don't send information while the LCD is busy. One is to just wait long enough for the LCD to finish. The other is to check the built in BUSY signal of the HD44780, I prefer this method as it is much quicker.

The Busy Flag:
RS:0
RW:1
DB:(BF(ADDRESS))

When we set RW to 1 (read/write) we read the busy flag as well as the address counter. To read the busy flag we set RW to 1 and then the E line from 1 to 0. This will put the busy flag on DB7. A simple BTFSS loop will allow you to check the busy flag.

Writing Data to the LCD:

Writing data encompasses several functions:

-Initializing the LCD
We set the proper functions for the LCD to operate and set it up for data transfer
-Selecting the first memory location
We send the first DDRAM address we want to write at (most parts sending 0x80 will set us to the first character)
-Writing the hex value for the char we wish to display

Command: Write
RS:1
RW:0
DB:Character

To write a char we just load the HEX value that corresponds to the data we wish to display, set RS to 1 and send the data (E1->0)

We keep writing as long as we want to stay on whatever line we started at. Every time you write, the address counter automatically increments, no need to keep resending the DDRAM address.

Command: Read
RS:0
RW:1
DB:Address Contents

This command reads the current address's contents.

With this, you have all the information to control the HD44780 based character LCD. I will be posting Code and a project involving this LCD so stay tuned!

 

Ground control to Major Tom. (Serial communication)

11/05/08 | by Jfkfhhfj | Categories: Informative, Code

One of the last modules you will come to know and love is that of the USART module. There are many communication modules that PIC MCUs offer, but USART is going to be one of the simplest and easiest to get off the ground, sending and receiving data.

Fundamentals of communication:

There are two predominate forms of communication serial and parallel. In serial you send bit after bit and parallel you send word after word. Parallel had an advantage before we got some fast transfer rates as it could transfer more data at lower speeds, but it required more infrastructure and it was more error prone as well as complicated. Serial communication is very simple and can be done with as little as two wires. Because of its simplicity we use serial communication. With the USART module there are two types of serial communication, they are synchronous and asynchronous. Either case we have a Baud Rate, or the clock speed of the transmission. We must declare the baud rate before transmission can be done so that the hardware is in sync and expecting results at the right time

Asynchronous:

Asynchronous is full duplex communication, which means you can send an receive data at the same time. We can do this because we have a dedicated wire for transmission(TX) and a dedicated wire for receiving data (RX) Data can be received and sent at the same time. This method is very simple to set up and you can have the same code on all your devices. It is primarily used for device to device communication where synchronization is not important.

Synchronous:

Synchronous is half duplex, which means you can only send data or receive it a given time. In this setup we use one wire as data and the other as clock. In this setup we have a master PIC that sets the clock rate and salve PICs that run off of the master's clock. This is very useful for multi device communication but it requires two sets of code, one for the master and one for the slaves. This however provides great control over your application where the master can control the show and the slaves collect and format data. Lets actually look at what we have to do to send data.

The Registers:

PIE1: (bank 1) Peripheral interrupt enable register 1. This is the register that controls what peripheral interrupts we have on. To use a peripheral interrupt we must first set INTCON bit 6 high. (INTCON,PEIE)

PIR1: (bank 0) Stores the flags for the peripheral interrupts.

SPBRG: (bank 1) Baud rate generator. We move a literal into here which correlates to a baud rate for transmission. The actual baud rate depends on what you send and what the settings for transmission are.

TXSTA: (bank 1)
Transmitter Status and Control register. This register controls weather we use asynchronous or synchronous communication as well as other functions related to the transmitter.

RCSTA: (bank 0)
receive Status and Control Register. This register controls various operation of the receiver and its associated properties.

TXREG: (bank 0) transmission register, we move values to here that we want to be transmitted.

RCREG: (bank 0)
receive register, bits received from transmission will be here. When we read this register the receive flag automatically clears.

Sample code:

#include 
     __config (_INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF)
org 0 
cblock 0x20
TEMP
DISPLAY
DELAY1
DELAY2
W_TEMP
endc
goto          PORTS;
org 0x04
INTERUPT:
	movwf     W_TEMP     ;Store w to TEMP
	bcf       INTCON,7   ; Turn of interrupts
	btfss     PIR1,RCIF  ; Wait until RCREG is full
	goto      $-1
	bcf       PIR1,RCIF  ;Clear flag
	movf      RCREG,w    ; Move RCREG to w
	movwf     DISPLAY    ; Move w to DISPLAY
	call      ROUTINE    
	movf      DISPLAY,w  ; Move DISPLAY to w
	movwf     PORTC      ; Move it to PORTC
	movf      W_TEMP,w   ; Restore w
	bsf       INTCON,7   ; Turn on interrupts
	retfie               
ROUTINE:
	bcf      STATUS,0    ;Clear flag
	rlf      DISPLAY     ;Rotate the display
	btfss    STATUS,0    ; Check flag
	return               ; Exit if not set
	movlw    0x01        ; If it is, reset display
	movwf    DISPLAY
	return
PORTS:
	bsf       STATUS,RP1 ;Bank 2
	clrf      ANSEL   ; All pins are digital I/O
 	clrf 	  ANSELH   ; All pins are digital I/O
	bcf       STATUS,RP1 ;Bank 0
	bsf       INTCON,7  ;Set up global interrupts
	bsf       INTCON,6  ; Peripheral Interrupts
	bsf       STATUS,RP0  ;Bank 1
	bsf       PIE1,5      ; Interrupt on RX buffer full
	bcf       STATUS,RP0  ; Bank 0
	bcf       PIR1,RCIF   ; Clear the flag
	bsf       STATUS,RP0          ; Bank 1
	movlw     0x00           ; Move the hex value of 0 to multi purpose register W
            movwf     TRISC          ; make IO PortC all output
	movlw     0xff           ; 0xff to w
	movwf     TRISA          ;PORTA input
;serial comm transmit
	movlw     d'25' ; Move the value of 25 or 0x19, to the baud rate generator
	movwf     SPBRG ; this will make the baud rate = to 9600 at a 4mhz internal clock in high speed mode
	bsf       TXSTA,BRGH   ;baud rate high
	bsf       TXSTA,TXEN   ;Enable Transmission
	bcf       TXSTA,SYNC   ;asynchronous
	bcf       STATUS,RP0 ;Exit bank 1
	;Serial comm Receive
	bsf       RCSTA,SPEN ;Set serial port enable high
	bsf       RCSTA,CREN ; Enable receiver
	clrf      PORTB     ; Clear 
	clrf      PORTC     ; Clear display
	movlw     0x01      ; Initialize Display
	movwf     DISPLAY
MAIN:
	bsf       PORTC,0   ; Portc high
	btfsc     PORTA,3   ; Poll the button press
	goto      $-1       ; Goto instruction - 1 
	call 	  TX        ; Call transmission
	bcf       PORTC,0   ; Clear port c,0
	call      DELAY     ; Call delay
	goto      MAIN
TX:
	btfss     PIR1 , TXIF  ; TXIF is set if TXREG has no character
 	goto      $-1          ; Loop until TXIF is cleared
 	movf      DISPLAY,w    ; Data to be transmitted over serial port
 	movwf 	  TXREG        ; Copy data to transmit register
 	bsf       STATUS,RP0   ; RAM PAGE 1
	btfss 	  TXSTA , TRMT  ; Wait until transmission is completed
 	goto      $-1          ; Loop back until transmission completed
	bcf       STATUS,RP0
 	return
DELAY:                ; Generic Dela routine
	decfsz   DELAY1
	goto     DELAY
	decfsz   DELAY2
	goto     DELAY
	return
end

This code is fairly complicated but its not horrible. This is basic code for asynchronous transmission which transmits a value, which triggers an interrupt for the receiving PIC. That receiving PIC then takes the transmitted value and performs an RLF operation on the data then out puts it to PORTC.

The Routine:

1) Startup – Declare environmental variables and goto main port routine
2) Ports – Set up the ports for digital I/O, Enable Interrupts, Enable peripheral interrupts, Enable asynchronous transmitter and receiver. Initialize Display to 1
3) Pool the button and wait for press
4) Button is pressed, Transmit DISPLAY by loading it into the TXREG register and waiting for it to shift out.
5) Delay is called to De-bounce switch.
6) Other PIC receives value, interrupt triggers when RXREG fills
7) Move RXREG into DISPLAY and rotate the bit (if carry reset to 0x01)
8) Return from interrupt

The Breakdown:

        ;serial comm transmit
	movlw     d'25' ; Move the value of 25 or 0x19, to the baud rate generator
	movwf     SPBRG ; this will make the baud rate = to 9600 at a 4mhz internal clock in high speed mode
	bsf       TXSTA,BRGH   ;baud rate high
	bsf       TXSTA,TXEN   ;Enable Transmission
	bcf       TXSTA,SYNC   ;asynchronous
	bcf       STATUS,RP0 ;Exit bank 1
	;Serial comm Receive
	bsf       RCSTA,SPEN ;Set serial port enable high
	bsf       RCSTA,CREN ; Enable receiver

That is the bulk of the code, This section sets up our PIC for serial communication.

The most important part of this section of code is the baud rate. We primarily derive the baud rate from the data sheet and the frequency we run our PIC at. We generally want the least amount of error for our application. For 4MHZ 9600bps in high speed mode is most efficient and least error-prone. If we look at the data sheet to set that baud rate we send 0x19 to SPBRG.

Because we want high speed mode, we get BRGH high, We want to enable the transmitter so we enable TXEN and we want asynchronous communication so we set SYNC to 0.

For RCSTA we want to enable the serial port so we set SPEN high and we want to enable the receiver so we set CREN high.

This is the basic setup for the most efficient asynchronous data transmission with a 4MHZ internal oscillator .

For synchronous and other types of setups refer to the data sheet, its all very self explanatory. One thing you have to consider, there is going to be different setups for the MASTER PIC and the SLAVE PICs.

TX:
	btfss     PIR1 , TXIF  ; TXIF is set if TXREG has no character
 	goto      $-1          ; Loop until TXIF is cleared
 	movf      DISPLAY,w    ; Data to be transmitted over serial port
 	movwf 	  TXREG        ; Copy data to transmit register
 	bsf       STATUS,RP0   ; RAM PAGE 1
	btfss 	  TXSTA , TRMT  ; Wait until transmission is completed
 	goto      $-1          ; Loop back until transmission completed
	bcf       STATUS,RP0
 	return

This is the primary code that does the transmission. We first poll PIR1,TXIF to make sure it is clear, then we move the value we want into TXREG starting the transmission. We wait for the transmission to complete and then we leave.

Once the other PIC receives a value it triggers an interrupt and the following code gets executed.

	btfss     PIR1,RCIF  ; Wait until RCREG is full
	goto      $-1
	bcf       PIR1,RCIF  ;Clear flag
	movf      RCREG,w    ; Move RCREG to w
	movwf     DISPLAY    ; Move w to DISPLAY

We wait until RCREG is full, then we move the value to DISPLAY (or wherever we want).

There we have it. Asynchronous data transmission from one PIC to another. Source and hex are below. Feel free to take and modify it. This will not be the only article on data transmission. This will be a topic we will be visiting frequently and getting very in depth with.

Source Assembly

Assembled HEX

 

Pointers

11/05/08 | by Jfkfhhfj | Categories: Informative, General, Code

Pointers are a very fundamental part of programming, often you need to reference a memory location without directly addressing or calling it, pointers help us do that. With c/c++ pointers can be a little daunting because how they work isn't directly apparent. Luckily for us, assembly works directly with the ram of the MCU and using pointers is extremely easy and almost effortless.

The use of pointers with a PIC mcu is called indirect addressing. We use the FSR(File Select register) and INDF. Essentially we load the value we want to point to into FSR and we address it using INDF. Fairly simple, lets look at an example:

VALUE equ 0x20

movlw   0x03
movwf   VALUE
movlw   0x20
movwf   FSR
movf    INDF,w
movwf   PORTC

The value on port c will be 0x03

First, we set up our variable VALUE to the general purpose address of 0x20.
Then, we set it equal to 0x03
We move the value of 0x20 to FSR (the location of VALUE)
Then we move INDF (The value of the address we loaded into FSR in this case 0x03) to w
Then w to PORTC

Very simple, with this in place you can save memory and make your programs extremely efficient and quick. Using the FSR and INDF will be essential to any remotely complicated code such as communications and robotics and other advance topics.

 

Time

11/04/08 | by Jfkfhhfj | Categories: Informative, General, Code

As your code gets more complex and so does the tasks you wish to perform its often important to take advantage of the build in hardware and gain the ability to multitask. One of the last modules to go over is the timer module. There are several timers build in but we will be focusing on the TMR0 module.

Using the module is fairly straight forward you can turn it “on” with about 3 lines of code. The TMR0 module is a 8 bit timer, thus after 256 clocks it carries over. We can also set a prescaler that sets what the ratio of the timer to the clock is. This prescale value has a max of 256 as well. With max prescaler our timer will reach a max time before rollover of 65536 instructions or .06 seconds. If you need a timer that lasts longer, the other modules hold larger values and thus rollover at a later time.

The Registers:

OPTION_REG: (bank 1) Holds timer configuration information.

The Code:

  #include (p16F690.inc)
     __config (_INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF)
org 0              ; Begginning of code
PORTS:
	bsf       STATUS,RP1
	clrf      ANSEL          ; All pins are digital I/O
 	clrf 	  ANSELH         ; All pins are digital I/O
	bcf       STATUS,RP1	
	bsf       STATUS,RP0
	movlw     b'0111'    	 ; Turn on 256 prescaler
	movwf     OPTION_REG
	bcf          OPTION_REG,3   ; Prescaler set to timer0
	bcf       OPTION_REG,5	 ; set timer for internal osc
	movlw     0x00           ; Move the hex value of 0 to multipurpose register W
              movwf     TRISC          ; make IO PortC all output
	bcf       STATUS,RP0
	clrf      PORTC
MAIN:
	movlw     0x01
	xorwf     PORTC
	btfss     INTCON,2  ; Check if timer overflow flag is set
	goto      $-1
	bcf       INTCON,2
	goto      MAIN
end


This code enables the timer and uses it to flash an LED when it rolls over.

Breaking it down:


movlw b'0111' ; Turn on 256 prescaler
movwf OPTION_REG
bcf OPTION_REG,3 ; Prescaler set to timer0
bcf OPTION_REG,5 ; set timer for internal osc

This is all the code we need for the timer module. It’s fairly straight forward. We mostly change OPTION_REG to set the timer for what we want.

OPTION_REG:

bit 7 RABPU: PORTA/PORTB Pull-up Enable bit

1 = PORTA/PORTB pull-ups are disabled
0 = PORTA/PORTB pull-ups are enabled by individual PORT latch values

bit 6 INTEDG: Interrupt Edge Select bit
1 = Interrupt on rising edge of RA2/INT pin
0 = Interrupt on falling edge of RA2/INT pin

bit 5 T0CS: Timer0 Clock Source Select bit
1 = Transition on RA2/T0CKI pin
0 = Internal instruction cycle clock (FOSC/4)

bit 4 T0SE: Timer0 Source Edge Select bit
1 = Increment on high-to-low transition on RA2/T0CKI pin
0 = Increment on low-to-high transition on RA2/T0CKI pin

bit 3 PSA: Prescaler Assignment bit
1 = Prescaler is assigned to the WDT
0 = Prescaler is assigned to the Timer0 module

bit 2-0 PS<2:0>: Prescaler Rate Select bits
(table in datasheet)

For the TMR0 module the bits we care about are 0,1,2,3 and 5. For basic operation we set bit 5 low, using the internal oscillator for the clock source. We assign the prescaler to the timer module and not the Watch Dog Timer. We also assign 111 to the prescaler which is the max value.

With that set, our basic code does a XOR operation with the current contents of PORTC, waits until the timer overflows by polling the TMR0 overflow flag bit (INTCON,2) and then returning to main and doing it all over again. In the end we get a blinking LED using highly efficient code.

There we have the TMR0 module in a nutshell. Most of the other timers work in a similar fashion. With this hardware under your belt the possibilities are endless.

Assembly Source

HEX

 

A2D

11/04/08 | by Jfkfhhfj | Categories: Informative, General, Code

It is often very useful to create a digital representation of an analog signal. The primary way we do this is through a analog to digital conversion. This is done by comparing Vin with a reference voltage (Vref) and converting their ratios to a binary number.

Fortunately for us the PIC microcontroller has analog to digital converters built into the hardware. Doing an analog to digital conversion does take time however, but it is an extremely valuable resource. We often use analog to digital conversions for sensor applications, or anything where voltage varies with conditions.
Doing an A2D conversion

As with everything in the PIC, the first thing we have to do is enable the hardware and then set up the port to do an A2D conversion.

The registers:

ADCON0: (bank 0) Stores the config information for the A2D module
ADCON1: (bank 1) Sets the clock for the A2D conversion
ANSEL: (bank 2) Determines whether a port is digital or analog, for A2D we obviously want whatever port were using to be analog
ADRESH: (bank 0 ) Results of conversion are here.

The Code:

    #include 
     __config (_INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF)
org 0                                               ; Beginning of code
DISPLAY equ 0x22                        ; DISPLAY var stored at General purpose register 0x22
PORTS:
	bsf       STATUS,RP0        ; select BANK 1
	movlw     0x00               ; Move the hex value of 0 to multipurpose register W
        movwf     TRISC              ; make IO PortC all output
	movlw     0xff                 ; Move the hex value of FF(255) to multipurpose register W
	movwf     TRISA              ; Make  PortA all inputs
	movlw     0x10               
        movwf     ADCON1         ;set A2d Clock to FOSC/32
	bcf       STATUS,RP0       ;Exit bank 1
	bsf       STATUS,RP1       ; BANK 2
	movlw     0xff     
	movwf     ANSEL            ; Set PortA for all analog 
	bcf       STATUS,RP1      ; Exit bank 2, Enter bank 0
	movlw     0x01            
	movwf     ADCON0      ; Configure ADCON and turn it on {Left just, VDD=VREF, RA0,A2D ON}
	clrf      DISPLAY             ; Clear Display Var
MAIN:
	call      A2D                    ; Call subroutine
	movf      DISPLAY,w     ; Move Display to w	
	movwf     PORTC         ; Move W to portC
	goto 	  MAIN            ; Return to main
A2D:
	nop              
	nop
	nop
	nop
	nop                               ; wait 5 uS
	bsf       ADCON0,GO  ; Start the conversion 
	btfss     ADCON0,GO ; Bit will stay high until conversion is complete
	goto      $-1                 ; Until then keep going back
        movf      ADRESH,w  ; Move result to w
	movwf     DISPLAY    ;Then w to Display
	return
 end

The Breakdown:

Most of the code is fairly straight forward, we set up the A2D module in the ports routine and then we do a conversion on RA0 and display the results on PORTC.

movlw     0x10               
movwf     ADCON1         ;set A2d Clock to FOSC/32

These lines move a literal into ADCON1, ADCON1 is the register for the clock of the conversion module, this one sets the time to the oscillator by 32, which is fairly slow. The higher the impedance of your input, the longer you should let the conversion take. The longer the clock, the more data you acquire and the more accurate your results are. However set this to what best fits your application


movlw     0xff     
movwf     ANSEL            ; Set PortA for all analog 

This merely tells the PIC to set porta up for analog signals, if you’re doing a purely digital circuit it’s wise to set these low

movlw     0x01            
movwf     ADCON0      ; Configure ADCON and turn it on {Left just, VDD=VREF, RA0,A2D ON}

ADCON0 is the configuration register of the A2D module, here you set the VREF source, how the data is outputted, and what port to run the conversion on and weather to start or stop the conversion. The datasheet explains what each bit does. This setup, we have our data left justified (A2D is a 10 bit operation, bit we only want 8, so we have the data start with the first 8 bits rather than the first 2), Our VREF is VDD, channel 000 is set (ra0) and we turned the module on.

A2D:
	nop              
	nop
	nop
	nop
	nop                               ; wait 5 uS
	bsf       ADCON0,GO  ; Start the conversion 
	btfss     ADCON0,GO ; Bit will stay high until conversion is complete
	goto      $-1                 ; Until then keep going back
        movf      ADRESH,w  ; Move result to w
	movwf     DISPLAY    ;Then w to Display

This is the main A2D subroutine. The module works by charging an internal capacitor; this takes time to charge so it’s always good practice to kill some time before the conversion starts. Once you set the ADCON0 GO bit high the conversion starts. After the conversion finishes the bit will go low, so we continue to poll that bit until it does so, and then we move the contents of ADRESH to wherever we want. In this case we move it to DISPLAY.
There we have it, a basic Analog to digital conversion. It is worth your time to check out the chapter on A2D conversion in the PIC hand guide. Good luck on your future code, the source and compiled hex are located below

Assembly Source A2D.asm

HEX

 

S vs C

10/21/08 | by Jfkfhhfj | Categories: Informative, Tips

This post is going to start off a new category: Tips.

Posts in the tips category are going to be generally short and they wont be chronologically significant. They are just meant to demonstrate common techniques and/or common errors.

There are two letters that will absolutely devastate your code if your not careful, they are s and c. s and c are used in most bit orientated instructions (bcf, bsf, btfss, btfsc). They stand for Set and Clear or 1 and 0 respectively. When making your code and going over your logic, make sure you note what you are setting high and what needs to be set low. Reversing these two letter will utterly change your code, often for the worst. I've had code that went from useless to perfectly working by changing only one letter. A tip for debugging code, ALWAYS simplify your code first and then always check your bit orientated operations and make sure you're using the right instruction. With that in mind you will spend more time programming and testing and less time debugging.

 

Expanding the PIC

10/08/08 | by Jfkfhhfj | Categories: Informative

Most of the code on the side barely scratches the surface of the PIC microcontrollers capabilities. There are tons of functions and features in an average PIC that makes they incredibly powerful and useful devices

Even though the PIC is a 2$ microcontroller at its maximum clock speed it is capable of doing 1 million instructions per second. An average program of sophisticated design only is about 100 or so lines in assembly will be executed 10000 times in a second. This is something you must consider when writing a program.

A good example of this is when asking for user input, you'd want to add a delay routine to account for the physical bouncing of the switch as a switch isn't a perfect on/off device a switches contacts will bounce several times before actually settling to a specific state.

Applications using timers want to have a routine that handles overflows so you have data integrity.

With a microcontroller speed and efficiency is a double edged sword, you want as much speed as possible and you want as much speed as possible both however lead to less data resolution. Slower clunkier routines tend to be more reliable and accurate (not always true) As a programmer you want to be on a middle ground between having reliable data and a quick update time


Interrupts

Interrupts are very crucial parts of taking advantage of a PIC microcontroller. An interrupt in a nutshell is a special case where the PIC will stop what its doing and go to the interrupt routine, after its done with that it goes back to where it came from and waits for the next one to trigger.

This makes software incredibly efficient as you don't have to keep checking the state of something hoping that you happen to catch it while its changing, instead you just enable it as an interrupt and have it execute code relative to its function.

There are several standard interrupts available on the PIC MCU as well as several special to each device.

All interrupt related bits are held in the INTCON register which is accessible through all banks

(For PIC16F690)

Bit 7 is the global interrupt enable bit, this is the bit that controls weather interrupts are enabled are not, you set this high when you want to use interrupts.

Bit 6 enables or disables the extra peripheral interrupts, this doesn't need to be enabled unless using the extra interrupts

Bit 5 enables the Timer 0 module overflow interrupt. Most all PICs have atleast one timer module, Timer 0 is an 8 bit module thus it overflows at a max value of 255. When it does this interupt triggers

Bit 4 is the RA2 interrupt pin, this triggers when RA2 is set high (as in a button press)

Bit 3 is the RA/RB change interrupt bit, this is for setting up the Interrupt on Change feature of PORTA and PORTB, after this is set you need to go to the register IOCA and IOCB for PORTA and PORTB to choose what pins trigger the interrupt

Bit 2 is the flag for the Timer 0 overflow interrupt, this flag is high when the interrupt occurs.

Bit 1 is the RA2 interrupt flag, this is set when the RA2 interrupt occurs

Bit 0 is the RA/B change interrupt flag, set when the RA/B change interrupt occurs.

Where does an interrupt go when it is triggered?

The org function tells the compiler where to place the code in memory, 0x00 is the beginning of the programming registers and 0x04 is where interrupts are stored.

An example:

org 0x00
goto PORTS
org 0x04
"Place interrupt here"
retfie
PORTS:
do work
MAIN:
do work

If you have your main function set up to loop, the program will go to the main function and loop until an interrupt is triggered. To exit an interrupt we use the retfie function which means return from interrupt

Things to consider:

-When you are working in an interrupt you WANT to save the w reg that was in the main loop before the interrupt was triggered. You do this by loading w into a temporary register you declared earlier.
- Save the STATUS register, the interrupt will change STATUS thus it is best to save it to a temporary value. However when restoring status you want to swap nibbles twice using swapf as to not set any flags by mistake.
- TURN OFF GLOBAL INTERRUPTS, you don't want another interrupt triggering so its best to turn off the global interrupt while in the actual interrupt until your done with the routine
- Clear all interrupt flags, clear the flags and if your using more than one type of interrupt use the flags to see which interrupt occurred *btfss/c*
- Restore w

Interrupts can be extremely powerful tools when used correctly. They are essential if you ever want to seriously start making effective and efficient programs. More to come on how to get the most out of your PIC coming up in the next few days so stay tuned!

 

The Microcontroller

08/24/08 | by Jfkfhhfj | Categories: Informative

Now that we've covered the basics we can finally get into the main purpose of this blog. From now on we will refer to a microcontroller with the acronym "MCU."

Section 1: The MCU

-So yea, what are they?

A MCU is a small computer on a chip. Most MCUs have RAM ROM and a CPU to process data stored in ROM. When a MCU is turned on, it instantly starts running the code stored in its data banks and executing commands. Most MCUs only have about a small amount of storage (usually a few KB ) but it more than enough to run complex algorithms and even stuff for advanced robotics. Microcontrollers are essential to all electronics they provide the ability to make a device “smart” without using complex analog integrated circuits or expensive computer systems. They are extremely fun for hobbyists as they can replace tons of expensive components with a moderately priced MCU.

-What can I do with them?

You can do almost anything. From dancing LEDS to PWM fan control to driving LCD screen and robotics. If you can code it, a microcontroller will do it. The fundamentals of a MCU are taking inputs and conditioning outputs through the use of code. Depending on the complexity of your code depends how complex the function of your chip can be. With a little creative thinking you can make even the low end chips do some extra ordinary things.

- What so special, I can do all of that with analog circuits!

Well, analog circuits aren’t as modular and expandable as MCUs. As soon as you compile your code your chip has taken on new functionality. Debugging and expanding functionality is extremely easy and efficient. A analog circuit that would take several integrated circuits as well as a dozen passive components can easily be replaced by one chip which does it all. MCUs can even use analog circuits to expand the function of circuits.

-What types of functions do these chips take on a day to day basis?

They're everywhere! Any interactive device uses MCUs. Your microwave, your television, your mouse, your cell phone, and pretty much everything use them.

-I mean with all this functionality, these things must cost a fortune!

Not at all, although high end chips can cost upwards of 20$, most mid range lines go for about 3-4$ each

Section 2: The world of MCUs


-This stuff sounds cool, but where do I start?

Getting into microcontrollers is much easier than it may seem. It’s always good to have a background in passive and analog components but its not necessary (will make things harder if you don't). There are many different types of microcontrollers. Some use proprietary languages some run on common languages like C/C++/Basic. Some require expensive software, some come with free software. For the purpose of this article I am going to be explaining how to work with the PIC series of microcontrollers manufactured by Microchip.

-So why the PIC?

They are low cost microcontrollers which are extremely easy to program for and develop with. They offer the latest support for their devices as well as free development software. PIC microcontrollers are widely used by hobbyists because of their ease of use and their cost effectiveness.

-What do I need to start?

You need a programmer,an actual MCU, and software to develop with. I highly recommend the PICKit2 offered by Microchip. They go for about 50USD and they include a USB programmer, tons of guides, the microchip IDE, and a midrange 20 pin PIC16F690.

http://www.microchip.com/stellent/id...cName=en023805

If you plan on using microchip MCUs you need their IDE (developers suite) offered free on their website (as well as included with PICKit2)

-There are literally thousands of MCUs to choose from! Which one do I use?

I personally like the 20 pin PIC16F690, I use in all my projects and I highly recommend it. It’s an 8-bit microcontroller with a 20MHZ internal clock it has 7KB of internal storage, but it’s more than enough for some basic robotics and any other projects.

You can buy them at http://www.mouser.com/Search/ProductDetail.aspx?qs=fM4xO01eazPcr2WIDQJ1Dg%3d%3d

Section 3: The mindset of a developer.

Rather than continue with my quirky Q&A style I am going to discuss some ideologies and strategies associated with working with MCUs before I get into programming and your first program.
You should have a good idea of how to work with binary numbers as well as hexadecimal. You will need to know them. I recommend you read the blog post before this one to get an idea of working with binary and hex if you haven't.

Every MCU has its own data sheet. They’re about 300 pages long and they contain every nook and cranny of the hardware. They are ESSENTIAL to develop for any MCU. When you get a device, you must understand how to reference data from a data sheet. The data sheet for the PIC16F690 is located below:

http://ww1.microchip.com/downloads/en/DeviceDoc/41262E.pdf

For the most part, you are programming WITH the hardware in mind. You are going to sending data to memory locations to enable functions and check statuses of certain memory locations. This is different than writing a program for windows or programming in C. The main parts of a microcontroller are its registers, registers are spots in the memory that have a function associated with them, and they start at 0x00 and end at 0x1fff. Most of it is empty memory dedicated for storage of your program, however in the beginnings there are dedicated locations for the functions of the MCU. These are where you set up ports and manipulate I/O data. The way Microchip sets up there memory is in two banks. Bank 1 is where you set up information on the ports and bank 0 is where you manipulate data. For the most part, the running part of your program is going to be in bank 0 and you only switch to bank 1 to set up ports.

The basic flow of a program is setting up environmental variables, then setting up ports, then going to a main routine that calls subroutines to analyze data and condition outputs. Programs for MCU tend to be very linear compared to code written for software. One thing to keep in mind is that your code operates very very fast. A PIC operates around 4MHZ and takes 4 clocks to do one instruction, thus an average PIC will operate at about 1 million instructions per second and an average instruction taking only 1 microsecond to complete. This both works with as well as against you. Flashing an LED isn't as simple as doing a loop that turns on and off a LED you have to add a delay routine in between so that the LED being on and off is visible to the naked eye. Considerations like these are learned as you work with your hardware and begin to notice what works and what doesn't work.

The Software

We will mostly be working with Microchip's MPLAB IDE. This software suit includes pretty much everything you need to use to develop for your PIC. It includes many different assemblers, compilers, simulators and programmers to make sure that your code will work flawlessly. Once you setup a new project and set up your hardware you will begin writing your code.

Section 4: The Hardware

Remember how i said how important the data sheet is? We're going to open up the data sheet of the PIC16f690 and explore the insides and learn how to work with this hardware. This data sheet includes data for several MCUs all are fairly similar except they come in different packages. We are going to be looking at the data for the PIC16F690 20pin DIP MCU.

One of the first things we see are the pin outs for our MCU. The first pin is the VDD which is the supply voltage, we always provide a 5v regulated source to our micrcontrollrs for safe operation, however it can accept a wide range of voltages (Try not to go above 9 V). Pin 20 is the ground. These two pins are the only two power pins essential to operation. There are several other pins you should also take into consideration when building circuits outside of the developer. Pin 4 is the MCLR which is a reset pin and also the pin that is used to trigger programming. You usually provide a logic high to this pin if you turn it on in the config word (The configuration file for the MCU set when programming). We also have a Clock in and Clock out on pins 2 and 3 respectively. All microcontrollers need a clock source to increment the code and keep things running. Most microcontrollers have an internal oscillator at 20 MHZ that is more than enough for us. However, you can set the clock manually by providing a clock source to these pins and configuring the config word to not use the internal oscillator.

After that we have our multipurpose input/output(i/o) pins. In the PIC16F690 the i/o pins are separated by ports a b and c. ports a and b arnt full 8 bit i/o ports but port c is. For the most part i use port c for output and a or b for input, in the end its just developers preference.

Different pins will have different functions and can be used for different things. All of that is described in the data sheets. You also want to keep note of what pins are used for external interrupts.

Next on our list is the register block (starts page 29). The next part of the data sheet goes on to explain the general location of all the registers and their hex location. Simple enough.

Our PIC microcontroller is a 8 bit device. Which means most functions can only handle a max of 8 bits. The table after the register block expands the basic registers and explains what each bit does (page 34).

Lets look at the status register. The status register controls the status of the micrcontroller. certain flags are set when certain things happen in the micrcontroller. The status register is also the go to register when you have to change banks. It is located at 03h (same as 0x03) and has 8 bits to it. This table does a basic layout of what functions are located at each bit, but if we want a more in depth explanation we can go look it up further into the data sheet.

The Status Register.

Page 38 explains the status register's bits more in depth. The mains bits were going to be using are 0, 2, and 5.

Bit 0: Bit 0 is the carry bit. It is set when a bit overflows (goes over 255 or below 0)

Bit 2: Bit 2 is the zero bit, it is set when the result of a arithmetic operation is 0 or negative.

Bit 5: Bit 5 is the RP0 bit. We set or clear this bit to change which bank we are in. The design of the PIC microcontroller is that there are two banks, bank 0 and bank 1. As explained earlier, bank 1 is where you set up ports and bank 0 is where you manipulate data.

The data sheet offers explanations for all the registers and everything so if you ever get stumped, go to the data sheet.

Section 5: Your First program

Although you can use C to develop for the PIC1690, I prefer assembly language. It’s much easier to work in assembly than it is with C as assembly is more tied to the hardware than C is. The following code was included in Microchip’s PICKIT2 it is not mine and I am merely including it for Demo purposes.

#include p16f690 .inc
__config (_INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF)
org 0
Start:
bsf STATUS,RP0 ; select Register Page 1
bcf TRISC,0 ; make IO Pin C0 an output
bcf STATUS,RP0 ; back to Register Page 0
bsf PORTC,0 ; turn on LED C0 (DS1)
goto $ ; wait here
end

The Registers used: STAUS, TRISC and PORTC

STATUS holds information on general MCU info, it has 8 bits to it however, were interested in the RP0 bit which controls what bank we are in.

TRISC is the tri-state register for portc, this also has 8 bits, by setting it high, we make that port an input. By setting it to 0, we make it an output.

PORTC this handles the data on the ports. We can check if inputs are high or low and we can set outputs high or low.

#include p16f690.inc The first line includes a file that has preset names for common register location (Such as STATUS, PORTA/B/C and TRISA/B/C

__config (_INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF)

This line set the config word for the MCU, this includes information about clock weather to use internal timers or not. For most intensive purposes, this general config can be used which uses the internal oscillator and turns off the MCLR

org 0 Tells the compiler this is the start of the program.

Start:
A label, we uses these to label parts in a program.

bsf STATUS,RP0 BSF, means BIT SET HIGH, the next lines tell it to goto the STATUS register and bit RP0, RP0 sets what bank the program is in, by setting it to 1(high) we are in bank 1 and thus can manipulate port information

bcf TRISC,0 BCF, means BIT CLEAR, The next lines tell it to goto the TRISC register (controlling portc I/O) and set the first bit, bit 0, to low, thus making it an output (1 is input, 0 is output)

bcf STATUS,RP0 This clears RP0 in STATUS, bringing us back to bank 0. Now we can manipulate data.

bsf PORTC,0 Sets the first bit of PORTC to high, enabling the LED

goto $ Stops the program

end Tells the compiler the code is finished.

What you can do with this you should build your code. By building your code you call MPLAB's assembler which takes your code and turns it into a HEX file that the PIC can read natively. After you do that it is highly recommended you run MPLAB's simulator and begin testing your code. You can watch the special registers and see how your code manipulates the registers as well as the I/O.

From here we can begin loading our code onto the actual MCU and set it up in a circuit. The PICKIT already contains a development area and several components to test the function of your code. However, for more complex programs you will be taking your PIC off the programmer and onto a breadboard to build even more sophisticated projects.

If you’ve survived so far, give yourself a pat on the back, for you have entered the world of MCUs. The possibilities are endless and with a little ingenuity the world is yours.

 

1001001 SOS

08/23/08 | by Jfkfhhfj | Categories: Informative

Binary, the language of machine, but why? In circuitry we have two things we can represent data as. We can use a "on" and a "off" meaning, weather there is current flowing or there is not. Traditionally 1 represents an on, or a high and 0 represents an off or a low. Because of this we work in binary, because there are only two numbers in that system 0 and 1.

Number systems

We work with the decimal system which has values 0-9. This was primarily done more than likely because we have 10 digits which we've used over the centuries to count :D (now if we only counted fingers and not digits we'd be perfectly happy with octal). Each digit in a number represents the base to a power starting at 0 and ending at infinity. To put this to perspective lets look at the number 142. When we break 142 apart we get:
1 4 2
1x10^2 + 4X10^1 + 2X10^0
100+40+2
142

This works for all number systems from binary to hexadecimal and beyond.

Binary

Lets look at a binary number, 1001001 and break it apart.

1 0 0 1 0 0 1
1*2^6 + 0*2^5 + 0*2^4 + 1*2^3 + 0*2^2 + 0*2^1 + 1*2^0
64+0+0+8+0+0+1
73

1001001 is a binary representation of the decimal number 73. Binary doesn't look so daunting anymore does it?

Bits and Bytes

If you've ever been around computers or anything digital you've heard the terms 8-bit 32-bit 64-bit 100 Gigabyte etc. One bit represents one digit of a binary number, either a 1 or a 0. A byte represents 8-bits or two hexadecimal digits(well get on hexadecimal later). Bits and bytes are the main ways computers handle data. Bits being fundamental and bytes being a way to organize bits in a way that they're useful. You cant hold that much information with a bit, however with a byte you can hold up to 256 values (2^8)

Hexadecimal

Even though bits are fundamental we are going to be working with hexadecimal. As you can see, to represent large numbers in binary can get rather confusing. We use hexadecimal to bring things down to size and make code and large registers more manageable. Hexadecimal is a number system based on base 16. If you noticed, 16 is a power of two thus every 4 digits in binary represent 1 hexadecimal digit. We note that a number is hexadecimal with the prefix "0x" or the suffix "h." One thing you might be wondering is how do you represent numbers greater than 9 without using two digits? Simple, we use letters. In hexadecimal we use the number 0-9 and the letters A-F (10-15). So the hexadecimal number 0xB is 11 in decimal and 1011 in binary.

Expanding Hexadecimal

So lets do a quick exercise to see how hexadecimal truly works. Lets start with 0x5FB

To convert this to binary we break it down digit by digit starting with the first.

0xB in binary is 1011. The second digit 0xF is 1111 in binary and 0x5 is 0101 in binary.

We put this all together and get 01011111011. Because hexadecimal is based on a number that is a power of 2, we can work with numbers like this.

Expanding it to decimal isn't all that hard either, however a calculator would help for those tricky powers of 16.

0x5FB
5*16^2 + 15*16^1 + 11*16^0
1280 + 240 + 11 = 1531

In reality, with a little work and patience working with other number systems will come natural and become easier the more you work with them. With the fundamentals of electronics, semiconductors and these number systems we can finally start looking at the microcontroller.

 

Truth tables NEVER lie

08/21/08 | by Jfkfhhfj | Categories: Informative

So we have diodes, resistors, transistors, capacitors, inducers, and whatnot. So how does this all come together to make computers?

At its heart, a transistor takes an input and provides an output. Alone its a fairly simple logic operation and transistors alone are usually used solely for switching current. However, when you combine them in fascinating ways you can create logic gates. Logic gates take inputs and provide outputs based on certain criteria. The simplest gates are NOT, AND, OR.

If you remember from high school mathematics, logic isn't that complicated. For these gates you have two inputs that are compared and an output that is determined by the input. The inputs will be A and B, the output Q and 1 represents high and 0 represents low.

NOT
Not is one of the most simplest gates, it takes the input and reverses it.
A->Q
1 0
0 1

AND
And merely outputs high when both A AND B are high, otherwise it outputs low.
A+B->Q
0 0 0
1 0 0
0 1 0
1 1 1

OR
Or outputs high when either input is high.
A+B->Q
0 0 0
1 0 1
0 1 1
1 1 1

Simple enough. We also have logic operations that are combination of the above. Combining OR and AND with NOT gives us NOR and NAND. This merely reverses the output as follows

NOR
A+B->Q
0 0 1
1 0 0
0 1 0
1 1 0

NAND
A+B->Q
0 0 1
1 0 1
0 1 1
1 1 0

Now ever more complicated we have logic gates that are slightly more complex. These are the Exclusive OR(XOR) and the Exclusive NOR(XNOR) gates.

XOR
The idea behind the XOR gate is that the inputs can be either or, but not BOTH. Hence it is exclusive to the OR function.
A+B->Q
0 0 0
1 0 1
0 1 1
1 1 0

XNOR
Reverse it.
A+B->Q
0 0 1
1 0 0
0 1 0
1 1 1

There we go, the simplest logic gates. With these logic gates we can make things like adders, flip flops and memory. We'll save the explanation of those for another day since it can get quite tedious.

Since the first post of this blog we've done a crash course in electronics, semiconductors and logic. Now that we understand the basics behind circuitry and electronics we can go ahead and start playing with our microcontrollers and begin learning how to make them do our bidding. Stay tuned as i go into the Binary and Hexadecimal number system and as we begin looking at assembly.

 

Semiconduct THIS

08/20/08 | by Jfkfhhfj | Categories: Informative

Even with the fundamentals laid down, electronics had little place to move in terms of computing. Vacuum tubes were very bulky and ate a lot of electricity to do simple tasks. Early computers took up whole rooms and had the computing power of most modern microcontrollers but, they did their job. It wasn't until the advancement of semi-conductors that we truly saw the miniaturization of electronics. With the semiconductor came the transistor and with the transistor and the advent of advanced photo etching processes we eventually got the integrated circuit and the microprocessor. This paved the way for modern electronics that now work on a scale of about 45 nanometers (a lone Si atom is .1 nanometers wide)

So what is so special about semiconductors? Silicon is the most famous semiconductor. Silicon in its natural state makes a nice lattice because it has 4 valance electrons and wants 8, so it bond with 4 other Si and makes a lattice. A lattice is very strong atomic structure and does not conduct electricity, thus making pure Silicon a insulator. However you can add impurities to silicon to change the way it conducts electricity. This is called doping. If you dope silicon with something like gallium(Ga)which has 3 valance electrons, you end up having a spare electron on the silicon that has no where to go. This lone electron is free to flow and thus, current flows. This type of silicon is called N-type and is a decent conductor. You can also dope silicon with something such as arsenic, which has 5 valance electrons. This creates a positive "hole" where a absence of electrons exists. Flowing electrons can take up this space and move the hole, this allows current to flow. This is called P-type and is also a decent conductor.

This is why silicon is a "Semiconductor" it will not conduct electricity in one state but will in another. Its not the states alone that are fascinating, but its what happens when you put them together.

The Diode

The diode is another fundamental component. Its basic function is to allow current in only one direction. This is crucial as it protects components and makes sure current only goes one way. It accomplishes this by creating a junction of P-type and N-Type silicon like so:
------------[(P-Type)|(N-Type)]------------

When you hook up a battery backwards like this:
(-)------------[(P-Type)|(N-Type)]------------(+)

The holes in the P-type are attracted to the negative terminal and the electrons are attracted to the positive terminal. No current is allowed to flow.

When you hook up a batter the correct way:
(+)------------[(P-Type)|(N-Type)]------------(-)

The electrons are repealed by the negative terminal as the holes are to the positive terminal. At the junction the electrons meet with holes and begin filling them. Current flows across the junction.

The diode only allows current to flow when it is properly placed in a circuit. However it isn't nearly as significant as the next component.

The Transitor

Without the transistor, none of this would be possible. The transistor is the modern computer. A transistor is merely a diode, but going one step further. A transistor features 3 layers of doped silicon usually arranged as PNP or NPN (hence NPN And PNP transistors) by adding this third layer, you can create a switching effect. In a PNP transistor by supplying current to the middle layer you allow current to flow throughout the device. This fundamentally allows a small current to switch a large one.

By having this ability you can begin to build Boolean gates out of arrangements of transistors. If you have logic you can make computers.

This is the story of the semiconductor! After it was born it was a mad dash to implement complicated logic gates as well as the race to make the transistor smaller and smaller. This race lead us to our faithful component, the Microcontroller.

 

Let there be light!

08/20/08 | by Jfkfhhfj | Categories: Informative

Our modern world would be nothing like it is today without electricity. Electricity has enabled man to create devices that truly work on an atomic scale. We can cram more power into smaller devices with more and more capabilities. What intrigues us most about electricity is that is based on such a simple concept.

Likes attract, opposites repel. Electricity is made from electrons (REALLY?) these electrons have a negative charge. The fundamental of electricity is to creates charge difference that induces electrons to flow. With this charge difference work can be done. Voltage is defined as the potential difference in charge, so where there is voltage there can be work done. By connecting two objects with a potential difference with a conducting material (wire) the charge evens out as the electrons flow from negative to positive. Now, when you take this idea and add fun things like semiconductors, you get our modern world.

The Fundamentals

All flowing charges are made up of two things, Current which is measured in amperage and voltage(potential difference) measured in volts. For a circuit to be useful there must be some type of resistance, without resistance, your current flows as fast as it can and as much as it can. This wastes energy and you might end up vaporizing your wire due to so much current and heat. So we invent these things called resistors.

A resistor just simple, resists electrical flow and slows things down. They produce a limit on current and they allow us to supply reasonable amounts of current to devices without them all catching on fire. Resistance is measured in Ohms.

The Formula

V=IR is one of the most important formulas you can ever get to know. It states that Voltage(in volts) is equal to Resistance(in ohms) multiplied by Current(in amps). This lets you determine how much resistance you need to supply to a voltage to limit to a set current, or any other adaptation.

Another fundamental component is the Capacitor. Capacitors are measured in Farads. The job of a capacitor is to hold a charge. It does this by placing opposing charges on opposite plates separated by a dielectric(insulator). By holding a charge a capacitor stores energy. Although they don't hold nearly enough energy to work as batteries, their main advantage comes form the fact they can discharge extremely rapidly. Common uses for this ability are the flash in your camera. The camera charges a large capacitor and dumps all the electricity at once into the light bulb, creating an intense flash. Capacitors are use in timing circuits, smoothing out ripples in power supplies, filtering frequencies and storing energy. Capacitors are extremely useful and find their way in practically every circuit.

The inductor. This component is about as simple as you can get. A inductor is simple a coil of wire. The special thing about a coil or wire is the fact it builds up a magnetic field when charge is put though it. As the current through the coil changes, the magnetic field resists this change. Because of this an inductor, like a capacitor can store energy in a magnetic field. Inductors are measured in Henrys. Inductors are primarily use to regulate frequencies since a capacitor and inductor in series creates a harmonic circuit.

With these fundamentals we were able to create simple devices such as radios and gain the ability to transmit power, generate locomotion and light our homes. It wasn't until the invention of the semiconductor and the transistor that our modern lives really took off.

 
February 2017
Sun Mon Tue Wed Thu Fri Sat
 << <   > >>
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28        

Ads by Google

Mcuplace.com Store!

This blog is dedicated to working with digital circuitry and the use of microcontrollers, small compact computers on a chip. I will be encompassing many techniques to develop projects, tools to use to write and assemble code and i will be sharing any projects i am currently working on. User feedback is a must! I do not know it all, hell im not even that experienced, but without a general place to get all the info needed i find it very hard to get into the world of microcontrollers without pursing a CE degree. So come one come all and enter the world of mystery and creativity!

Search

  XML Feeds

blog software