This section describes all instructions for the 8-bit AVR in detail. For a Constant literal or byte data (8 bit) k: Constant address data for program counter b. AVR™ Enhanced RISC Microcontrollers. Atmel Corporation is a leading manufacturer of a broad range of high performance, low power nonvolatile memory and. Hi all, In the AVR Studio help topic for the ATmega16/32 Instruction Set it says For a detailed description of the Instruction set, refer to the AVR.
|Language:||English, Dutch, Hindi|
|ePub File Size:||25.85 MB|
|PDF File Size:||20.23 MB|
|Distribution:||Free* [*Sign up for free]|
Figure 4 shows the AT90S AVR Enhanced RISC microcontroller architec- The bytes data SRAM can be easily accessed through the five different. Source register in the Register File. R: Result after instruction is executed. K: Constant data k: Constant address b: Bit in the Register File or I/O Register (3-bit) s. AVR 8-Bit Microcontroller. ATmega8A Data Sheet. Introduction. The ATmega8A is a low-power CMOS 8-bit microcontroller based on the AVR® enhanced RISC.
The debugWire interface enables debugging using only one pin the Reset pin , allowing debugging of applications running on low pin-count microcontrollers. The board includes the LCD screen, joystick, speaker, serial port, real time clock RTC , flash memory chip, and both temperature and voltage sensors.
The AVR Butterfly comes preloaded with software to demonstrate the capabilities of the microcontroller. Factory firmware can scroll your name, display the sensor readings, and show the time. The AVR Butterfly also has a piezoelectric transducer that can be used to reproduce sounds and music.
A pre-installed bootloader program allows the board to be re-programmed via a standard RS serial plug with new programs that users can write with the free Atmel IDE tools. Only the JTAG port uses conventional 2. Atmel ships proprietary source code included but distribution restricted example programs and a USB protocol stack with the device. All these boards support JTAG-based development. The kit includes two AVR Raven boards, each with a 2. The radios are driven with ATmegap processors, which are supported by a custom segmented LCD display driven by an ATmegap processor.
AVR RISC Microcontroller Handbook by Claus Kuhnel
These are intended for use in developing remote sensor nodes, to control relays, or whatever is needed. Polling occurs when a section of code, usually an infinite loop in main , looks to see if an event has occurred. Interrupts are much like interrupts in daily life. The telephone, for instance, interrupts your activities by its insistent ringing. But imagine how it would be if you had to poll the telephone to receive calls. Microcontrollers respond to interrupts much like you would.
Maybe you are reading a book and the phone rings.
Microcontroller Interrupts and Timers to the line you were reading and dog-ear the page before closing the book. From the hardware perspective an interrupt causes the microcontroller to stop what it is doing, store sufficient data so that later it can get back to what it was doing, look to see which interrupt happened, run the interrupt code, and when finished restore the machine to its state before the interrupt occurred using the previously stored data.
Interrupts are great, but they provide an avenue for some particularly pernicious bugs. For example when your code is reading an integer from memory and since an integer is made of two bytes it gets the first byte, then is stopped by an interrupt that changes the value of the integer before returning control to the part of the code that was reading the integer which then gets the second byte of the integer.
The integer will be wrong because it will be made half from the pre- interrupt value and half from the post-interrupt value. The crazy making debugging problem is that the interrupt can happen at any time, maybe only very rarely during the integer read. Your system can run like a champ and then locks up for no apparent reason. If you compare the software used in this example to the Butterfly software you might think I stole some of it.
That is one of the central principles of software engineering: Heck, if it is nailed down, get a crowbar and rip it up. Microcontroller Interrupts and Timers Some of this code will have concepts that will be explained later. Expect a little confusion. Now may be a good time for a nap.
The Atmega data book lists 23 interrupts in Table 22 on page Two of these interrupts, the Pin Change Interrupts: The joystick pins map as follows: A 0 disables the interrupt for a pin. To enable the buttons of interest: Since some other part of the software might be using that bit, we want to leave it as is. The statement: If this is still obscure get out the pencil-and-paper-computer and play with it a bit.
It is a critical concept for understanding microcontrollers. We are going to use: If we put: So we can write: We set them to enable the PCI1 interrupt as follows: We use the following code to access the PCI1 interrupt: Interrupt handling is defined specifically for a particular microcontroller and a particular C compiler and it is not portable like most of C.
In Programmers Notepad change Demonstrator. Using joystick Using HyperTerminal, you should see: Microcontroller Interrupts and Timers You are talking to the Joystick demo.
The joystick position is: LEFT Move the joystick to the right and you should receive: UP Move the joystick down and you should receive: DOWN Push the joystick while centered t and you should receive: In Blinky. This loop runs in the CPU, which can do nothing else while it is running. Knowing the time per cycle allows you to set the time of the delay. Cycle wasting delays are a simple way to control some types of periodic events, but the simplicity comes at the cost of totally occupying the CPU while wasting the specified time.
The bothering can take the form of setting a flag that the CPU can poll, or throwing an interrupt to break into normal operations. The pulses can come from a synchronous periodic source providing an accurate time count, or the pulses can come from an asynchronous non-periodic source providing an accurate count of the input pulses. In the first case we could be counting pulses from the In the second case we could be counting pulses from a light beam interrupter circuit and keep an accurate count of the number of people entering a door and breaking the light beam.
A timer overflows when it counts up to its maximum value for the 8 bit and for the 16 bit devices and resets to 0. We can get the Timer to overflow at lower values by putting a value in the OCR, Output Compare Register, for the specified timer and that timer will compare the value with the count and when they match it will set a flag or throw an interrupt.
It can also be set to overflow to 0 on a match. The timers can be configured for input capture events, where a change on a pin will cause the timer to save the count when the event occurred.
This input capture count can be used to measure the width of external pulse. If the external pulses are periodic, we have a frequency counter. Poll the overflow flags. Break program execution with an interrupt.
Let the timer automatically change the level of output pins. The clock source for the prescaler can be an external clock such as the Microcontroller Interrupts and Timers Calibrating the Butterfly oscillator: If you try to tell time with the uncalibrated oscillator built into the ATmega, you can expect to gain or lose a couple of hours a day.
Real time is determined by the National Bureau of Standards and references an atomic clock. To calibrate the built-in oscillator to real time requires an external crystal that has been precisely trimmed to pulse in time with the NBS clock. The Butterfly uses an external We can get an accurate count of a time period by counting pulses from the watch crystal.
For instance if we count pulses we know that one second has passed. We use a shorter known good period to calibrate the internal oscillator by setting the oscillator to generate x pulses in the known good time period. Remember that the oscillator is running at about 8 MHz, so we are going to get a lot more counts from it than we will get from the watch crystal. If we count pulses from the watch crystal and 8 million pulses from the oscillator in the same period, we know the 8 MHz is accurate.
That is, we get 8 million counts from the oscillator in the same period we get counts one second from the crystal meaning the oscillator is running at exactly 8 million pulses per second. But we will actually use a much shorter period and have smaller counts.
If the oscillator count is too small for the period we change the value in a register to speed it up, and if it is too large we change the register to slow it down. We do this in a loop to keep bracketing the speed until it gets as accurate as we can make it.
In this section we will learn how the Butterfly oscillator is calibrated. Getting registers set properly to do much of anything in a microcontroller can be a long and frustrating exercise, and another good reason to steal code where possible.
We start calibrating by running a loop in which you make adjustments to the internal oscillator and comparing the results to the external clock, looping until you get it right. Set a flag: Microcontroller Interrupts and Timers Disable global interrupts: If so set our temp variable to 0xFFFF. It IS mighty confusing. And frustrating and bug infested and time consuming and ego destroying and… well, you name it.
But finally getting something working is the greatest pleasure known to mankind, if you overlook sex, eating, parenting, and anything else you like to do.
A word of advice: Then we set a compare value of so the timer throws an interrupt every counts: We set timer0 to do a compare interrupt: The lowest bit toggles the LED times a second, it is on for th of a second then off for th of a second, which yields a blink period of Hz. If we tell the Butterfly to set the compare to , then the interrupt occurs at Hz and the fastest blink period becomes Hz.
Microcontroller Interrupts and Timers What happens if we send it ? How do we get a 60 Hz blink? We can get LED3 to blink at 60 Hz if the base rate is Hz, which we can get from interrupts per second, which we could get from a compare count of If we set the compare to we get a rate of But is it close enough?
A compare of throws an interrupt every millisecond. Using Precision Blinking: In HyperTerminal you will see: You are talking to the Precision Blinking demo. Setting the Compare Timer Count to: Okay, I lied; it is actually named for… hey, you can Google this as easily as I can.
For an equal interval pulse train the pin is high half the time and low half the time. When the pin is set to low, 0 volts, no current flows so the LEDs are off. The current flows thru ohm resistors providing 9 mA of current and a power of.
In the precision blinking project we were only giving the LED power half the time. If we keep the frequency of pulses constant, but lower or raise the on time it is on, we can control the power to the LED and the light output from it.
Microcontroller Interrupts and Timers We have already seen that the human eye perceives fast blinking LEDs as being constantly on. Our eyes also see rapidly pulsed light as having brightness somewhere between the peak and the average. This means that a high intensity pulse with a low duty cycle pulse looks brighter than it would powered by a direct current providing the same power as the average of the pulsed signal.
Our perceptual peculiarity gives us a way to provide a brighter seeming light with less power if we use PWM. This is good news for our power use, but bad news in trying to extrapolate duty cycle to perceived brightness. Cutting the duty cycle in half does not translate into a halving of the perceived brightness. Is it hard to write the PWM code?
Create a new directory, PWM, and copy the. In the Demonstrator files milliSecInit routine change: That was sooooo. I actually managed to burn up both the optoisolator and the power transistor when fooling with this design so, at least for me, this is not overkill. Microcontroller Interrupts and Timers The motor base is made with foam core board you could use corrugated box board cut and glued crappily to hold a motor. The upright on the left will be used in the next project to hold an optointerrupter.
Motor Base Figure Print it out and stick it to a piece of sturdy thin cardboard. I put some electrical tape on the motor shaft and made some radial cuts in the center of the wheel and slipped it over the tape. It works. The cutout will be used in the next project. Microcontroller Interrupts and Timers Speedometer We used an optoisolator to separate the motor power circuits from the Butterfly to help lessen the likelihood of blowing something up.
A device similar to an optoisolator is an optointerrupter, which has an air channel between the IR light emitting diode and the IR detector transistor, see Figure We can tie the transistor to a pin on the Butterfly and detect the interruption. Did you notice the opening cut in the wheel in Figure 22? If we write our software so that a voltage change on the pin attached to the optointerrupter causes an interrupt in the Butterfly, we can count those interrupts.
If we count for exactly one second we have the number of times the wheel rotates per second, which is the rotational speed in Hz. Solder long wires to the optoisolator, and then add electrical tape to prevent the legs from shorting.
Next carefully glue it to the motor base in a position so that the wheel rotates thru it. Make sure the wheel is balanced and will turn cleanly easier said than done and fully block and unblock the optoisolator slot as the wheel turns, Figure Microcontroller Interrupts and Timers Figure Though most kindergarteners could probably do a more attractive job than I did, it works.
Speedometer Create a Speedometer directory and copy the motor control software to it. Make the following changes in Demonstrator. Microcontroller Interrupts and Timers break; case 'H': We reused the pin interrupt code from the joystick software and in the interrupt routine we increment a speed counter variable.
Microcontroller Interrupts and Timers the power to the Butterfly, move the joystick to the up position for a moment, and you should see something like the following: But what do you expect for cardboard and glue? C Pointers and Arrays Chapter 8: C Pointers and Arrays Addresses of variables During the stone age of computers, when C was written, programming was done by positioning switches and looking at lights.
One set of switches represented data another represented the address of a memory location that you wanted to stick the data. Addresses are sequential and represent contiguous memory locations. I would set a data byte then set an address two bytes and push a button to write the data to the SRAM. When it was all loaded, I pressed another button to start the I bet you can guess what I had the program do. Later I wrote a program that allowed the to communicate with an original IBM PC and download large programs from the PC, and once loaded — run them.
I carefully wrote my primitive bootloader on paper in assembly language, then translated it from assembly to machine code, then hand entered it. The bootloader was only 81 bytes long. I bragged about this incessantly and saw many a set of eyes glaze over.
Anyone who knew anything about what I was doing suggested, after rolling his eyes to clear the glaze, that I get an EPROM programmer and write my code on a PC, like a normal person. Some of us prefer to do things the hard way if something is to be learned and I learned beyond any doubt just how hard it is to correctly enter 81 lousy bytes on a hand made computer.
That experience more than any other, burned into my mind the relation of data and addresses, a seemingly trivial relation until you get to C where this topic causes more confusion and bugs than any other.
Data is stored in memory locations — real tangible things made of silicon. These locations have addresses — information about the whereabouts of memory locations. Memory is a place. Addresses tell us how to find the place.
Stay ahead with the world's most comprehensive technology and business learning platform.
Sometimes confusion occurs when we realize that addresses are just numbers and can become data that can be stored in memory locations having… addresses.
The data at one memory location can be the address of another memory location whose data may or may not be an address. Data is just a number, in our case an 8-bit byte.
When the data is the address of another location of data it is called a pointer. C Pointers and Arrays to confuse is why C gurus love pointers and will go to incredible lengths to obfuscate their code with them.
Pointers are the reason that many refer to C as a mid-level rather than a high level programming language. In high level languages the programmer only deals with data and the compiler makes all the decisions about the addresses. In low-level languages, like assemblers, the programmer assigns the addresses to the data. In C, we are not required to play with addresses, but are allowed to if we want to.
And, dangerous as they are, some things can only be done using pointers. Pointers also allow us to do many things more efficiently and cleverly than would otherwise be the case.
There are many reasons to use pointers, as a simple example consider writing a function that will do something with data from a sequence of contiguous locations in memory.
Say you have a string: If we want our function to handle this sequence, we could send all 23 bytes as parameters to the function, meaning that they would all be pushed on the stack before the function call and pulled off by the function. But we know that we need to go light on the stack in microcontrollers, so we would like to us a different method. Now instead of using 23 parameters and pushing 23 bytes on the stack we only have to use one parameter and push only two bytes addresses are ints, which as you may remember are two bytes long.
Sounds simple, and it is once you get the hang of it, but unfortunately many novice programmers use pointers in much the same way a toddler would use an AK C Pointers and Arrays when they are used carelessly, and it is easy to create pointers that point somewhere unexpected.
With discipline, however, pointers can also be used to achieve clarity and simplicity. That byte was only occasionally important enough to crash the system. When your computer crashes intermittently with no apparent rhyme or reason, you may well be suffering from a bad pointer use. It can be a damn hard bug to find. To recap: You can have pointers to data, pointers to pointers, pointers to pointers to pointers to Wait till you run into things like: Be very afraid.
More examples: Function Arguments Arguments are passed to functions by value, and as we saw in an earlier discussion of functions, there is no way for a function to affect the value the variable passed to it in the function that did the passing. We could have func2: Arrays Arrays are groups of consecutive objects. Formally, we would define and initialize an array for this in C as: Any array-subscripting operation can also be done with pointers. Pointers are said to be faster than arrays, but they are much harder to understand for novice programmers and those of us with rapidly diminishing brain cells.
Since speed is an issue in microcontrollers, and pointers are faster we need to learn how pointers and arrays relate and apply it in code segments that must be made to run faster. Okay, what about: For c1 we added 1 to the address of confuseus before we dereferenced it with the indirection operator.
Double groan. We can express the array position using pointers: Change the Demonstrator. C Pointers and Arrays Confuseusmoreandmoreandmore.
Enough is too much. Simple, easy and straightforward. Real software from real working programmers: This function is used in vcard. C Pointers and Arrays This is a perfectly good function, but it requires that the user never ask for more bytes than the size of the pBuffer array.
The obvious answer is that the mistakes we make will often be painfully dumb. Stacks and Queues Circular Buffers Stacks Assembly language programmers frequently use the stack when calling subroutines and running algorithms.
Stacks are like those piles of trays in cafeterias, we take trays off the top and the dishwasher piles them back on the top. The top trays are usually wet and the bottom trays never get used. In control applications it is sometimes convenient to have fifos, private stacks, to manipulate data. The last one in line is the last one to get a tray. A circular buffer is more like a game of hot potato where the students form a circle and pass a hot pototo from one to the next and it keeps circulating indefinitely around.
The hot potato in our analogy is actually the pointer to the next address in the queue. For real students it would probably be a joint or a bottle of cheap alcohol. The question is: We can declare a pointer to a function as follows: If we have another function declared: Complex Pointer and Array Algorithms C is an ideal language for solving complex data processing and scientific computing problems. Many a computer scientist has made a living being clever and publishing the results.
Which is good for us, because almost any complex problem we will come across has already been solved for us. Whether its sorting a database or doing a really fast Fast Fourier Transform, the algorithm will be published somewhere convenient. It functions like ROM, but can be rewritten using special hardware and software functions. RAM is like money and beauty, you can never have too much of it, but in microcontrollers you can often have too little: C programs require RAM.
You can write assembly programs that can be burned into ROM, and run on microcontrollers that have no RAM, but C requires RAM to keep a stack for parameters and return addresses and to store arrays, among other things. But our C compiler puts arrays in the data section of RAM.
If we have lots of constant data in arrays, say strings, or conversion factor tables, or timing and tone data for songs, we are going to needlessly lose a lot of RAM. The following is an example of how to store a string and an array in flash ROM, and keep it there: The details get more complex than we want right now so just thank the guys who figured this out for you by sending them some money at: We send this string to the PC by defining a sendFString function: We can send a string as follows: Or we could use the simpler: Using an array of pointers to arrays.
The first time I saw an array of pointers to arrays I thought somebody was either putting me on or trying to obfuscate the code for job security. You fouled up beyond repair. Enter a 1 for error message: Situation normal, all fouled up. Enter a 2 for error message: Stop the madness!
Enter a 3 for error message: Where did you learn to program? Enter a 4 for error message: Read the freaking manual! In the software we store these string arrays in addition to the error arrays: The messenger software.
This will save us the RAM that has up to now been wasted on constant strings. In Programmers Notepad create a new file Messages. You are talking to the 'Messenger' demo. C Pointers and Arrays Enter a 0 for error message: Test it as follows: C Pointers and Arrays Does anybody know what time it is? A Real Time Clock. This was derived from the more capable clock in the Butterfly software. A one second interrupt We saw how to use the We start the software by using a delay loop to wait for the external crystal to stabilize.
Converting Computer Time to Human Readable Time We can keep a count of seconds, but what good does it do us if our watch reads ? C Pointers and Arrays indicate that the time is ten minutes and 41 seconds after eleven in the morning.
And that conversion is easy compared to the numbers you get if you set your watch at thirty-three seconds after three twenty in the afternoon on May 11th of and you are reading the number two years seventy-eight days six hours fourteen minutes and seven seconds later. So we are going to need to do some computing to convert the count to something we can read.
We can divide an 8-bit byte into two 4-bit nibbles each of which can represent a number with a range of 0 to And it allows us to store as single decimal integers, 0 to 9, in a nibble and two in a byte, one integer in each nibble.
If a the decimal number in a byte is less than 99, we can convert it to a BCD byte using the following algorithm: Set the initial byte in C we use char to some two digit value.
C Pointers and Arrays After this runs the initialbyte now contains only the ones integer from the original byte and high char contains the tens, that is: We combine the high and low nibbles to get the converted byte. We define two bytes Tens and Ones and a third byte, Number, which we set to a value in the range of 0 to So the conversion of a decimal integer to its ASCII equivalent character is the simple addition of 48 to the decimal integer. Create a new directory, Real Time Clock, and copy the.
Open Messenger. After compiling and loading the code, in HyperTerminal you should see: You are talking to the 'Real Time Clock' demo. Enter 'get' to get the time and date.
Enter 'secXX' to set the second to XX. Enter 'minXX' to set the minute to XX.
Enter 'hourXX' to set the hour to XX. Get the current time: Set the current time as follows: C Pointers and Arrays Music to my ears. In use: All nice and C like. Especially not repeatedly: So this is a miraculous little free compiler send them some money at: Martin Thomas, Kaiserslautern, Germany mthomas rhrk. When you finally learn enough to really evaluate the Butterfly code, you will come to appreciate the intelligence and hard work that this gentleman my assumption did for you.
Yes, you. And for free. So when you see the way he translated the relatively simple appearing song selection statement, you can agree with his comment below: C Pointers and Arrays First look at his version of the definitions: And the actual use is as follows: Yep, I agree: I doubt seriously that I have the time or the skill.
What the statement says is: What we are doing is sending this address to a function that knows how to extract a pointer to Flash RAM. Looks too complicated… but so what, it works.
Setting the frequency Tones are setup by putting an integer from the song table in the Timer1 Input Capture Register 1, ICR1, which in this case is used to set the counter top value. The values are taken from the Butterfly code and are based on a cpu clock running at 1 MHz.
We select a base frequency of Hz the A note and calculate the frequency for subsequent notes using the notes position on the musical scale following a. For instance, C0 is 3 after A: We get the frequency to generate for the tone with: We then compensate for our using a 2Mhz cpu clock by doubling the value using a left bit shift of one position.
A few tones from the sound. It begins by getting the tempo from the first position of the array and putting it into a Tempo variable. It continues to do this until the Tempo is 0, when it rereads the tempo and starts over. C Pointers and Arrays Setting the duration The duration and the frequency are paired values in the table. The duration is the length of time that the following tone should be played.
It starts the tone and then exits. When called again by Timer0, if the Duration is not 0, Duration is decremented and the function exits leaving the tone playing. If the Duration value read from the table is 0, this indicates that the tune has been played through, so it checks the next byte and if that byte is 1, it starts the tune over, if 0 it ends the tune. Clever, eh? It contains a sheet of material that deforms when electricity is applied to it the piezo electric effect. This deformation can be made at audio frequencies allowing the element to produce sound waves in the air.
Our piezo-element is connected to PortB pin 5, which is also the OC1A pin that can be configured as an output for the Timer1 waveform generator. We will configure the Timer1 waveform generator so that it will use PWM to generate tones. We initialize Timer1 to generate a PWM waveform as follows: A lower value of Volume will produce a higher volume.
Except that we actually only shift it right by 7 bits to adjust it cut it in half to compensate for the use of a 2MHz system clock in this applications for the USART when a 1 MHz clock was used in the original Butterfly code.
Create a new directory: Play it again Sam, and copy the. A high byte will give a low tempo, and opposite. Copy the sounds. Change the contents of the messages. C Pointers and Arrays break; case 'd': C Pointers and Arrays if! This is what you should see in HyperTerminal, and an example of use: You are talking to the 'Play it again Sam' demo.
Enter 1 for Fur Elise. Enter 2 for Turkey march. Enter 3 for Minuet. Enter 4 for Auld Lang Syne. Enter 5 for Sirene1. Enter 6 for Sirene2. Enter 7 for Whistle. Enter - to decrease the volume.
Enter stop to stop the music. All was well except for a tiny problem with the voltage measurement. Tiny as in the first time I tried to measure voltage on the Butterfly I destroyed it. Well destroyed is a bit harsh.
Fortunately I know myself so I had ordered six Butterflys because, as I said elsewhere, my nickname is Smoky Joe since my favorite learning method is producing copious quantities of smoke in my hardware projects.
It just died. Belly up, legs in the air, ready for a pin thru the thorax to be box mounted in the Dead Butterfly Museum. But Lepidopteron death is not what this is about. Lets just say this event led me to becoming a bit paranoid about the voltage measurement part of the Butterfly hardware and I went forward on tiptoes and slightly hyperventilating as I proceeded with the ADC code. My next version was able to read the light just fine, and the temperature just fine, and the voltage just one time.
When I requested: The reading is 1. And promptly died. No further responses to the PC. Sound crazy? Well, it seems that the light sensor affects the Butterfly voltage reference and we have to measure the ambient room light to calibrate the voltage reference before we measure volts.
So I covered the light sensor and the Butterfly still crashed. Then I went the other direction and put a bright light on it to no avail. So I thought that if its all that sensitive to light derived voltages maybe the USART traffic voltage is propagating about unpredictably and screwing things up.
In HyperTerminal I got: Hours passed and still no fix. I messed with the USART initialization function, the ADC initialization function, the ADC read function, the oscillator calibration function and generally had myself a merry old goose chase for about half a day. Finally, in total desperation, I tried what I should have tried in the first place. Eventually I got to the getVolt function and started commenting out sections. This is a time consuming process, each time you comment something out, you have to recompile, load, and test the code.
It takes a while. So here is the getVolt code: Finally, because there was nothing logical to try, I commented out the itoa functions.
And the Butterfly no longer messed up.
The itoa function is in the standard library, so I assumed that it must have a problem. I changed it to the itoa function and the other support functions that we wrote at the end of Chapter 6. Guess what? They also fail! I went for a long walk.
Later, after more staring at the function I noticed: They work just fine in the original Butterfly code. But many years ago I learned the hard way that if you assign memory to an array and then foolishly write beyond that memory, say to voltintpart, the third element of the array which only has two elements you will in fact write to the byte in memory that follows the array bytes which may not cause a problem if nothing else is using that byte, or it might just change it from the ASCII code for an explanation point to the Microsoft extended ASCII code for a black club.
So I enlarged them to: Good question. My guess is that the standard library functions were written to be as fast and small as possible. They also likely assumed nobody would be stupid enough to send it an array that was too small, and if they are that dumb, they deserve what they get.
C is fast, small, and mean. Other higher-level languages provide even more protection and are even larger, slower, and more complex. I acknowledge that the arguments for the choice of a programming language borders on the religious, so I say that if you choose not to use C, you will be eternally damned. Debugging can be a maddeningly frustrating process, especially if you are on a deadline. I spent half a day finding this problem. Am I stupid? This kind of debugging is part and parcel of working with microcontrollers.
If you have the wrong attitude, you will drive yourself nuts trying to find these bugs. What is the right attitude? It is to understand that you have to be really smart, work very hard, and know a lot about C programming and microcontrollers to make a mistake this dumb. You have to keep telling yourself over and over: During a discussion with one of my EE professors about Analog to Digital Conversion, I made the mistake of bringing up Heraclitus and Democritus and the ancient debate about the fundamental nature of reality: Analog to Digital Conversion by Successive Approximation We want to measure voltage, and in the real world, voltages can be any value whatever, they represent a continuum of electromotive force.
There are many ways to convert an analog signal to a digital value each having strengths and weaknesses, we will examine successive approximation since that is what the AVR uses. This method uses an analog comparator and a digital to analog converter. If the voltage on the DAC is lower than the external voltage, the analog comparator outputs a 0, if it is higher it outputs a 1. We have bits to play with so we can keep approximating in 0.
We use a binary search technique that starts in the middle and bisects each successive voltage. We start by bisecting the 3 volts by sending the number to the DAC, which then outputs 1. So we bisect the 1. Next we bisect the 1. We keep successively approximating until we find that the voltage is between1.
This is the best we can do with 0. During conversion the voltage is held constant by a sample and hold circuit. Look in the data book on page , figure 82 for a block diagram of the ADC circuit. We can use an external voltage reference attached to this pin, or we can tell the AVR to connect it to either AVCC or to an internal 1.
The Butterfly uses a nF capacitor for this purpose. These pins are connected to an analog multiplexer that can connect any of the pins to the analog comparator. Since the ADC consumes power it is recommended that you turn it off when not in use. An ADC interrupt can be set to trigger when a conversion is complete. Starting a Conversion There are several ways to start a conversion. This bit stays high while the conversion is in progress and is cleared by the hardware when the conversion completes.
The trigger source is determined by setting the ADTS2: The triggers can be: You can use higher sampling rate frequencies, but you get lower resolution. The first conversion takes 25 clock cycles to initialize the hardware. Normal conversions take 13 clock cycles and auto triggered conversions take Changing Channels There are some complexities involved in changing channels and voltage references that lead to the recommendation that you always wait till a conversion is complete before making a change.
If this is inconvenient, read the data book and figure it out yourself. We can put the system to sleep to shut it up and then take our ADC readings in the quietened environment. Details in the data book. Conditioning the Analog Input Signal The accuracy of the conversion will depend on the quality of the input signal.
A few recommendations: Accuracy The data book has some cursory discussion of the extremely dense topic of ADC accuracy. The ADPSx bits select the prescaler. The resistance of the LDR decreases as the light increases, so the voltage measured will decrease as light decreases. We write the getLight function: I have no idea what the data means other than the amount of light is inversely proportional to the data sent back, just like it is supposed to be. Temperature Meter We will measure the temperature in Fahrenheit and use an array of constants to convert the value from a voltage to a temperature.
The table is from the Butterfly code. When a table entry is found that is less than the ADC result we break and i equals the temperature in Fahrenheit.
Pretty clever, huh? I'll quit owning up to all this theft and from now on if you see something clever the good kind of clever just assume that I stole it. Change the Demonsrator. Compile, load, and test. You are talking to the ADC demo. The temperature is 78 degrees Fahrenheit. Turn on a fan! Put a flashlight on the light sensor and type in: The light reading is somethings.
Using the room light and type in: Put your finger over the sensor to block the room light and type: Urrrrmmmm… Oh yes, if we are going to measure voltage, we need to put a voltage on pin 2 of J on the Butterfly. But first we need solder some wires on a potentiometer so we can vary a voltage. By turning the potentiometer shaft we move a wiper connected to the center wire up or down.
Voltage measurement Now we can get some responses.
Try turning the potentiometer to various settings and in response to a volt command you should see something like: Since Digital Oscilloscopes normally cost tens of thousands of dollars, you can expect some compromises. This thing is very very very … very slow. We will output the look-up table data on port D and attach the pins as shown in Figure An R-2R resistor ladder looks a little magical, and the circuit analysis, though simple in concept, turns out to be fairly complex, but it makes a reasonably accurate DAC for very little cost.
The 2. Using the 2. Now you can read the output using HyperTerminal and have a really slow crappy sideways oscilloscope as shown in Figure R-2R resistor ladder Figure Square Wave Figure Sawtooth Wave Your skills as a C programmer should be to the point where you can read and understand all the software for this project without further comment.
C Structures Chapter C Structures Structure Basics A structure is a collection of variables that may be of different types all grouped together under a single name. They are like records in other programming languages and form a data unit that is convenient to handle. In software we can refer to me as: Structures can come in all sizes.
A small one would be useful in the PWM project to link the pulse frequency to the pulse width. A larger one could be used in the RTC project to link together all the time and date variables into a unit.
We can declare a structure: C Structures between pulseFreq and pwm. The structure declaration creates a data type, and like other data types variables can be declared to be of that type: The first declaration of pwm did not have a variable list following it, so it exists as a prototype and no memory is allocated.
In the second version, where we added the variables, pulser1,pulser2, and pulser3, we actually create three copies instances of the structure in memory. Structures and Functions You can do four things to a structure: Copy it 2. Assign to it as a unit 3. We could approach this three ways: Pass components to the functions separately. Pass an entire structure to the function. Pass a pointer to a structure to the function.
C Structures We will write a function makePWM to initialize a PWM structure by accepting an int and an unsigned char as arguments and returning a pointer to a pwm structure. We can use makePWM to dynamically initialize structures: We can save stack memory by defining a function to use struct pointers as paramerters: We use this function as follows: C Structures Structure Arrays In the last section we used: But there are cases where arrays of structures come in real handy.
Typedef C allows us to create new data type names with the typedef facility. Only actual C types can be aliased in this manner. Typedef works somewhat like define, in that it provides an alias, but defines are handled by the preprocessor and more limited in what they can do. Typedefs are useful in making software more readable: Byte makes more sense in our use than unsigned char.
Another use is to facilitate portability of software by putting machine specific types in typedefs so you can change them as you change machines. C Structures Unions A union provides a way to have a type that may be of different sizes depending on the circumstances of its use. We use a union in prgmspacehlp. This cluster can be a single bit, as would be used for a flag, or a 4-bit nibble, or any number of bits you might want to define.
These fields can be very useful, but unfortunately, in many microcontrollers, these bit-fields slow things down the compiler promotes bit to larger data types so for efficiency sake, bits are best dealt with using bit masking, which compiles to faster and smaller assembly code.
Bit masking simply uses a constant to define the position of a bit in a byte and allows you to read or write only that bit using the bitwise operators.
We will look at the C-way, since we are learning C, then the mask-way since we want to be as efficient as possible. Bit-Fields the C-way In our examples above we have often declared an object as an unsigned char when that object could only have two values: Using bit-fields we can declare eight similar variables in a single unsigned char note — not true for WinAVR, which promotes them to eight bytes.
We could define: C Structures to control a loop: We could have used: Now we control the loop: In the real world, our compiler would allow us to use the above syntax, but would assign 8 bytes to do the job.
First we get the address of the Port B registers from io And that ends this discussion. And I must admit that there are graduate level Computer Science courses taught on this subject, so it can get very scary indeed.
The basic ideas behind finite state machines are used to tame systems that seem impossibly complex. A computer is a finite state machine. Actually you and I can be seen as state machines. How does the software keep track of what it is doing?
How does it know to keep doing it? How does it know when to do something different?We have bits to play with so we can keep approximating in 0. Enter 1 for Fur Elise. In future projects we will only need to make changes to Demonstrator.
Next we set the DDRD register so that all the pins are used as outputs: C Pointers and Arrays when they are used carelessly, and it is easy to create pointers that point somewhere unexpected.
If you do, review.
- DATA BOOK FOR MACHINE DESIGN
- HC373 DATASHEET EBOOK
- CCNA DATA CENTER 640-911 PRACTICE EXAM EBOOK
- CA3086 DATASHEET DOWNLOAD
- CD7377CZ DATASHEET PDF DOWNLOAD
- 1M0565R DATASHEET EBOOK DOWNLOAD
- ACCOUNTING DATABASE DESIGN PDF
- OFFICIAL GUIDE GMAT REVIEW 11TH EDITION PDF
- MACHINE VISION RAMESH JAIN PDF
- NA DRINI CUPRIJA PDF
- LULA MAGAZINE PDF
- TROUT FISHING IN AMERICA PDF