Embedded system: MSP430g2553 IAR programming ports/pins BASIC Input / Output syntax - c

To put it simply : How do I define and use ports / pins correctly in IAR EW with MSP430g2553?
Ill use example to clarify what I do not understand.
I have a simple state machine with 3 states. I want to program 3 pins for input and 2 pins for output.
Then, depending on inputs I manage state.
First, is this correct way of defining inputs / outputs ?
P1DIR |= BIT0 + BIT1; //pins 1.0 and 1.1 output
P1DIR &= ~BIT2 + BIT3 + BIT4; // pins 1.2 , 1.3, 1.4 input
The above seems to me fairly straightforward to use, however, bigger question is how do I reference input pins in code ? And how do I set output based on input?
To further my problem, here is my starting code for this state machine and I've put in pseudocode where I dont understand how to write syntax. Would be of great help if anyone could fill in the pseudocode and commentate a bit. I've looked many tutorials but I dont seem to get this simple thing from them.
# include "msp430g2553.h"
# include "stdio.h"
# include "math.h"
#define START 1
#define LEFT_ON 2
#define RIGHT_ON 3
char STATE;
main ()
{
P1DIR |= BIT0 + BIT1; //port 1.0 and 1.1 output
P1DIR &= ~BIT2 + BIT3 + BIT4; // port 1.2 , 1.3, 1.4 input
WDTCTL = WDTPW + WDTHOLD;
STATE =START;
while(1)
{
//STATE = START;
switch (STATE)
{
case START:
{
// Starting state I want both outputs to be set 1, I dont know how
set p1.0 to 1
set p1.1 to 1
puts("START");
//check inputs to switch state
if (1.2 == 1 & 1.3==0 & 1.4==0) {
STATE = RIGHT_ON;
} else if (1.2 == 0 & 1.3==0 & 1.4==1)) {
STATE = LEFT_ON;
}
break;
}
case LEFT_ON:
{
// Here I wish to to put 1.0 output to 1 and 1.1 output to 0
p1.0 set to 1
p1.1 set to 0
// now check if 1.3 is 1
if (1.3 == 1) {
STATE = START;
}
break;
}
case RIGHT_ON:
{
// Here I wish to to put 1.0 output to 0 and 1.1 output to 1
p1.0 set to 0
p1.1 set to 1
// now check if 1.3 is 1
if (1.3 == 1) {
STATE = START;
}
break;
}
}//end of Switch
}// end of while
}// end of main

First, is this correct way of defining inputs / outputs ?
I assume P1DIR is the correct data direction register (I don't know this particular MCU in detail), but apart from that: no, it isn't correct. First of all, use bitwise OR | not addition. They give the same result but + makes the code look strange and a bit harder to read. The average C programming book will tell you to do:
P1DIR |= BIT0 | BIT1;
Note that P1DIR |= ... will leave all pins currently set as output as they are. That may or may not be what you want.
To set a port pin active then simply do the same, SOME_PORT_REGISTER |= PIN_MASK;. Similarly, you can toggle a single pin with ^= which is bitwise XOR. Or set it to zero with &= ~(mask).
P1DIR &= ~BIT2 + BIT3 + BIT4; is wrong, ~ is a unary operator that only applies to one operand. Corrected code:
P1DIR &= ~(BIT2 | BIT3 | BIT4);
I've looked many tutorials
Most tutorials on the web are unfortunately quite bad. Start by reading a decent C programming book before anything else. Once you've learnt the basics of C, you can go look for tutorials.
For example this article about register access I wrote here, it assumed that the reader already knows C: How to access a hardware register from firmware?
As for full beginner tutorials, I think this one has better quality than most: Embedded Software in C for an ARM Cortex M, Jonathan W. Valvano and Ramesh Yerraballi. (It's Cortex M not MSP430 but the principles are very similar no matter MCU. The same author also has an older tutorial that used NXP HSC12 examples, which is another 16 bitter even more similar to MSP430.)

Related

Controlling one single bit on a certain port in AVR chips using macros in C

I have experiences in AVR programming with CodeVisionAVR. Recently I switched to using Atmel Studio and found a minor but annoying problem: I can't control each PIN/PORT as easy as I did in CodeVisionAVR.
Firstly, let's initialize one certain port:
// Initialzing one port, for example PORT D:
// Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=Out
DDRD=0x01;
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=1
PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (1<<PORTD0);
// After initializing, Port D bit 0 should be the only pin set to out.
In CodeVisionAVR, I can do this:
PORTD.0 = 0; // Set Port D bit 0 to low
PORTD.0 = 1; // Or to high
But in Atmel Studio, addressing Port D bit 0 as PORTD.0 gives me an error. I have to do this instead:
PORTD = (1<<PORTD0); // Set Port D bit 0 to high
PORTD = (0<<PORTD0); // and low
As you can see, addressing by shifting bits is much less clean and harder to read / write. I thought CVAVR used something like a struct to imitate the dot (.) addressing method (in C we don't have classes), or some overloaded operators, or some macros, but after digging the included header files in CVAVR, I could only find this:
sfrb PORTD=0x12;
// ... other ports ...
sfrb PIND=0x10;
My question is, can I imitate the bit addressing method of CVAVR in Atmel Studio? If yes, how? Or was that some IDE-exclusive feature?
What you are saying about CodeVisionAVR
PORTD.0 = 0; // Set Port D bit 0 to low
PORTD.0 = 1; // Or to high
is not a valid C semantic, so if you didn't make a mistake on your predicate it must be a codevision compiler extension.
That kind of assignment in C represent an struct access, but you can not declare a struct member (or any other identifier) starting with a number, so PORTD.0 will produce an error.
Also when you do this:
PORTD = (1<<PORTD0); // Set Port D bit 0 to low
PORTD = (0<<PORTD0); // and high
you are not doing what you comment, you are assigning (assuming PORTD0==1) 0x1 to PORTD in the first expression and 0x0 in the second. If your intention is to manipulate only one bit, this is what you should do:
PORTD |= (1<<PORTD0); //sets bit PORTD0 high in PORTD
PORTD &= ~(1<<PORTD0); //sets bit PORTD0 low in PORTD
PORTD ^= (1<<PORTD0); //toggles PORTD0 in PORTD
You should read about bit manipulation in C, here is a post with more examples
Sometimes those actions are encapsulated in a macro, this an example of how you could do it:
#define BitSet(Port,Bit) (Port|=(1<<Bit))
#define BitClear(Port,Bit) (Port&=~(1<<Bit))
#define BitToggle(Port,Bit) (Port^=(1<<Bit))
#define SetBits(Port,BitMask) (Port|=BitMask)
#define ClearBits(Port,BitMask) (Port&=~BitMask)
#define ToggleBits(Port,BitMask) (Port^=BitMask)
//then you can use it
BitSet(PORTD,0) ; //Sets the bit0
BitSet(PORTD,1) ; //Sets the bit1
BitSet(PORTD,2) ; //Sets the bit2
// or
BitSet(PORTD,PORTD0) ; //Sets the bit0
BitSet(PORTD,PORTD1) ; //Sets the bit1
BitSet(PORTD,PORTD2) ; //Sets the bit2
...
SetBits(PORTD,0x55) ; //Sets the bits 0,2,4, and 6. Leaves the other unchanged
ClearBits(PORTD,0x55) ; //Clear the bits 0,2,4, and 6. Leaves the other unchanged

Programming AVR in C

I'm using an Atmega328. I have output pins that are "randomly" distributed along the pinout, i.e. they don't belong to the same ports. For example, my output pins could be PB0, PB4, PC1, PC3 and PD1.
I have always used Assembly to program microcontrollers, so this would be my first time using C. What I want to know is if there is a way to avoid using DDRx and Px for each pin to set them or clear them.
For example, I would like to use something like this to set the first bit of Port B:
#define NAME_1 DDRB,0
sbi NAME_1;
Is this possible?
EDIT:
Maybe I didn't express myself clearly. What I want is to be able to refer to certain I/O port pins with some meaningful names. For example, name PD3 "blue_LED", so that the code is more readable and, if the blue LED's position is changed later, the code can be easily modified. Stated another way, I want to be able to turn on and off certain pins with their names not being hard-coded. Is there a way?
The sbi instruction is special in that it directly manipulates a bit in an I/O Port on the AVR platform. The normal course with I/O ports is that you have to use other instructions (like out) to copy whole words between the I/O port and a register.
That said, there's no sbi in C. C just doesn't know about these special features of one particular platform. For the assembly you give as an example, you would write in C:
DDRB |= 1<<0;
I personally think this looks quite concise, but of course you COULD define a macro
#define sbi(x,b) (x) |= 1<<(b)
sbi(DDRB, 0);
(where b is the "bit number") and maybe the other way around
#define cbi(x,b) (x) &= ~(1<<(b))
cbi(DDRB, 0)
This would work, but I recommend not to use it. While the first notation DDRB |= 1<<0; is obvious to any C programmer, using macros like this probably isn't.
As a final note, if you are concerned about performance: I haven't verified this, but I'm pretty sure avr-gcc is smart enough to emit sbi and cbi instructions when a bit mask operation on an I/O port effectively just changes a single bit. edit: see JLH's answer for an experimental result that gcc-avr indeed is smart enough to emit these sbi/cbi instructions.
I use avg-gcc on to program Atmel AVRs and the support packages most definitely know about cbi, sbi, and all instructions for that matter. So there's no need to resort to assembly unless you want to. Here's some disassembled C to prove it.
PORTD |= (1 << PD0);
d8: 58 9a sbi 0x0b, 0 ; 11
Now I'll show you how. You can set each bit of each port to do either input or output very easily.
DDRA |= (1<<PA0);
has the effect of making pin 0 on port A an output as shown:
bit76543210
00000001 // or-ing the 1 adds 1 leaving the other bits alone.
To also make pin A3 an output, do this:
DDRA |= (1<<PA3);
bit76543210
00001001 // now the DDRA register looks like this, pins 0 and 3 set as outputs
Tedious, right? Well, these right-side expressions evaluate to constants so you can combine these into one statement:
DDRA |= (1<<PA0) | (1<<PA3);
and the compiler will fold the right hand side into one constant and |= it into the register. So, you really need only one statement like this per port, and the compiler makes it very efficient.
That takes care of direction -- input or output. The next is to set and clear outputs.
To set an output:
PORTD |= (1<<PD); // turns pin 0 on port D on (high) as an output.
PORTD &= ~(1<<PD); // turns pin 0 on port D off (low) as an output.
PORTD ^= (1<<PD); // toggles it (high-> low) or (low->high as an output.
EDIT:
To the extra requirements you named about using meaningful names, of course you can do that. I routinely do this to avoid having to remember what's connected to what. For example, from that same project:
#define LED_INDICATOR_PIN PA0
#define LED_INDICATOR_PORT PORTA
#define LED_INDICATOR_DDR DDRA
I refer to the 'friendly' names in my code:
void initialize(void)
{
// Set up an output pin to blink an LED to show sign of life.
LED_INDICATOR_DDR |= (1 << LED_INDICATOR_PIN);
// Set up TTY port.
init_uart();
}
void toggleLED(void)
{
LED_INDICATOR_PORT ^= (1 << LED_INDICATOR_PIN);
}
Much easier to read. Is that what you're after? I know it's what I do every time.
With C++ I wrote something like this:
//IO = I/O Subsystem
inline void Io_LEDred_Configure() {DDRB |= 1<<0; } //Port B0
inline void Io_LEDred_On() {PORTB |= 1<<0; }
inline void Io_LEDred_Off() {PORTB &= ~(1<<0);}
inline void Io_LEDgreen_Configure() {DDRD |= 1<<3; } //Port D3
inline void Io_LEDgreen_On() {PORTD |= 1<<3; }
inline void Io_LEDgreen_Off() {PORTD &= ~(1<<3);}
If you have to switch an IO to a different port you have to change only those three lines and you're done.
In C++ the compiler emits exactly that code what you as an assembler coder would write. In C you have to use a regular function. But the calls coming with some overhead. If you want to avoid this you have to use macros:
#define IO_LEDRED_CONFIGURE DDRB |= 1<<0
#define IO_LEDRED_ON PORTB |= 1<<0
...

Having trouble setting up the UART on an AVR Atmega88-PA

I want to set up the UART on a ATmega88-PA. First I was trying to set an interrupt on UDRE register but this was not working, so for the transmission I use normal polling.
Because the code was not working I started again from 0 with a basic program.
#define F_CPU 1000000UL
#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 8UL))) - 1)
char ReceivedByte = '#';
int main (void)
{
UCSR0A = (1 << U2X0);
/* Turn on the transmission and reception circuitry. */
UCSR0B = (1 << RXEN0) | (1 << TXEN0);
/* Use 8-bit character sizes. */
//UCSR0C = (1 << UCSZ00) | (1 << UCSZ01);
/* BAUD prescale */
UBRR0 = 12;
/* Load upper 8-bits of the baud rate value into the high byte of the UBRR register. */
//UBRR0H = (BAUD_PRESCALE >> 8);
/* Load lower 8-bits of the baud rate value into the low byte of the UBRR register. */
//UBRR0L = BAUD_PRESCALE;
UCSR0B |= (1 << RXCIE0);
sei();
DDRB |= 0x04;
PORTB &= ~0x04;
for (;;)
{
/* Do nothing until data have been received and is ready to be read from UDR. */
//while ((UCSR0A & (1 << RXC0)) == 0) {};
/* Fetch the received byte value into the variable "ByteReceived". */
//ReceivedByte = UDR0;
if(ReceivedByte == '1')
PORTB |=0x04;
else
PORTB &=~0x04;
/* Do nothing until UDR is ready for more data to be written to it. */
while ((UCSR0A & (1 << UDRE0)) == 0) {};
/* Echo back the received byte back to the computer. */
UDR0 = ReceivedByte;
}
}
ISR(USART_RX_vect)
{
ReceivedByte = UDR0;
}
And the code is working but when I open an arduino serial monitor and connect my module to that, I receive my poor # but alog with some garbage. Not all the time but mostly, the garbage is 1 or 2 byte. Can someone help me?
EDIT: It seams that when I send from my bleutooth data to a Samsung galaxy S3 the data is perfect...I do not have any clue why on serial monitor, and also when sending data using the same bluetooth to laptop I got a lot of garbage along with the data. If this helps you
answearing my qestion, will be great.
EDIT: sorry forget the last edit, it is send only a char ok, I change the char and also garbage is there. When I send a string is unreadable.
EDIT : As I commneted on the post below of embedded_guy , I solve the problem inserting a _delay_ms(1) after sending each byte. and it is working right now. I believe the statement
while ((UCSR0A & (1 << UDRE0)) == 0) {};
is not doing its job. Hope this will help others.
I don't know if this will work for you, but I really only see a couple of things that could be an issue.
First, all of the examples of setting the BAUD prescale that I could find used two instructions with the high and low registers of UBRR0. If you have already stepped through your code and examined that register to ensure that it is correctly configured, then that is not the issue. Otherwise, I would recommend setting it like this for the value you have it set to in your code:
UBRR0H = 12;
UBRR0L = 0;
The other thing I see is that you are never setting UCSR0C. You have it commented out and I would expect it to operate correctly with its default (reset condition) settings, but it is always good to be explicit just in case.
Finally, you may want to take a look at this page on Simple Serial Communications.
EDIT
Based on your most recent edit, I would take the bluetooth out of the picture. I would recommend connecting a logic analyzer to the UART transmit pin of your microcontroller and see if the data coming out of the atmega is what you expected. If that data is good, I would begin looking at why the bluetooth is not working as I anticipated.
try to use F_CPU with at least 2MHz
make your ReceivedByte volatile, try it like this:
volatile unsigned char ReceivedByte;

Setting up multiple timers with AVR

I am trying to set up two timer interrupt routines with Teensy 2.0 Microcontroller (which is based on ATMEGA32U4 8 bit AVR 16 MHz) for independent control of two servo motors
After much trial - I was able to set one up on pin 7 of port C, but
How do I set up the second ISR to be initialized and called independently of the first?
Do I need to setup the second timer and, if so, what would such code look like?
Here is the setup code:
int main(void)
{
DDRE = 0xFF;
TCCR1A |= 1 << WGM12; // Configure timer 1 for CTC mode
TCCR1B = (1<<WGM12) | (1<<CS11) ;
OCR1A = 1000; // initial
TIMSK1 |= 1 << OCIE1A; // Output Compare A Match Interrupt Enable
sei(); // enable interrupts
// ...code that sets pulseWidth based on app logic variable.
// Not showing as its not important
}
ISR(TIMER1_COMPA_vect)
{
if (0 == pulseWidth)
{
return;
}
static uint8_t state = 0;
int dutyTotal = 20*1000;
if (0 == state)
{
PORTC |= 0b10000000;
OCR1A = pulseWidth;
state = 1;
}
else if (1 == state)
{
PORTC &= 0b01111111;
OCR1A = dutyTotal - pulseWidth;
state = 0;
}
}
While it's difficult to give a definitive answer without knowing more about your application (e.g. what kind of servo/motor, - I'm guessing model RC type with 1-2ms pule?) there are two approaches to solving the problem:
Firstly, In your code you seem to be manually generating a PWM signal by toggling PC7. You could add another output by increasing your number of states - you need one more than the number of servos to give the gap which sets the pulse repetition frequency. This is a common technique when you need to drive a lot of servos, since most RC servos don't care about pulse phasing or frequency (within limits), only the pulse width, so you can generate a bunch of different pulses one after the other on different outputs while only using one timer like this (in a sort of pseudo-code state diagram):
State 0:
Turn on output 1
Set timer TOP to pulse duration 1.
Go to state 1:
State 1:
Turn off output 1
Turn on output 2
Set timer TOP to pulse duration 1.
Go to state 2:
State 2:
Turn off output 2
Set timer TOP to pulse duration 3.
Go to state 0:
"Pulse duration 3" sets the PRF (pulse repetition frequency). If you want get fancy,
you can set this to 1/f-pd1-pd2, to give a constant frequency.
[ "TOP" is AVR-speak for the thing that sets the wrap (overflow) rate of the timer. See data sheet. ]
Secondly, there is a much easier way if you're only using two servos - use the hardware PWM functionality of the timer. The AVR timers have a built-in PWM function to do the pin-toggling for you. Timer1 on the mega32 has two PWM output pins, which could work great for your two servos and you then don't (necessarily) need an interrupt handler at all.
This is also the right solution if you are PWM driving motors directly (e.g. through an H-Bridge.)
To do this, you need to put the timer into PWM mode and enable the OC1A and OC1B output pins, e.g.
/*
* Set fast PWM mode on OC1A and OC1B with ICR1 as TOP
* (Mode 14)
*/
TCCR1A = (1 << WGM11) | (1 << COM1B1) | (1 << COM1A1);
TCCR1B = (3 << WGM12);
/*
* Clock source internal, pre-scale by 8
* (i.e. count rate = 2MHz for 16MHz crystal)
*/
TCCR1B |= (1 << CS11);
/*
* Set counter TOP value to set pulse repetition frequency.
* E.g. 50Hz (good for RC servos):
* 2e6/50 = 40000. N.B. This must be less than 65535.
* We count from t down to 0 so subtract 1 for true freq.
*/
ICR1 = 40000-1;
/* Enable OC1A and OC1B PWM output */
DDRB |= (1 << PB5) | (1 << PB6);
/* Uncomment to enable TIMER1_OVF_vect interrupts at 50Hz */
/* TIMSK1 = (1 << TOV1); */
/*
* Set both servos to centre (1.5ms pulse).
* Value for OCR1x is 2000 per ms then subtract one.
*/
OCR1A = 3000-1;
OCR1B = 3000-1;
Disclaimer - this code fragment compiles but I have not checked it on an actual device so you may need to double-check the register values. See the full datasheet at http://www.atmel.com/Images/doc7766.pdf
Also, you perhaps have some typos in your code, bit WGM12 doesn't exist in TCC1A (you've actually set bit 3, which is FOC1A - "force compare", see datasheet.) Also, you are writing DDRE to enable outputs on port E but toggling a pin on port C.
Halzephron, thank you so much for your answer. I dont have the high enough reputation to mark your answer, hopefully someone else will.
Details below:
You are absolutely right about being able to use a single IRS to control a number of servos - embarrassing I did not think of that, but given how well your simpler solution worked - I'll just use that.
... Also, you are writing DDRE to enable outputs on port E but toggling a pin on port C.
Thanks, I commented out that line, and it works the same - (so I dont need to enable output at all?)
Bit WGM12 doesn't exist in TCC1A (you've actually set bit 3, which is FOC1A - "force compare", see datasheet.)
I removed that too, but leaving the rest of my code unchanged - it results in servos moving slower, with way less torque and jittering as they do, even after arriving at desired position. Servo makes a weird "shaky" noise (frequency ~10-20, I'd say) and the arm it trembling, so for the reasons I don't understand - setting this bit seems necessary.
I suspected that a timer per motor is highly inelegant, and so I really like your second approach (built - in timer-generated PWM),
... This is also the right solution if you are PWM driving motors directly (e.g. through an H-Bridge.)
Very curious, why? I.e. what's the difference between using this method vs, say, timer-generated PWM.
In your code, I had to change below line to get 50HZ, otherwise I was getting 25HZ before (verified with a scope)
ICR1 = 20000-1; // was 40000 - 1;
One other thing I noticed with scope was that the timer-generated PWM code I have - produces less "rectangular" shape than the PWM code snippet you attached. It takes about 0.5 milliseconds for the signal to drop off to 0 with my code, and its absolutely instantaneous with yours (which is great). This solved another problem I had been bashing my head against: I could get analog servos to work fine with my code (IRS-generated PWM), but any digital servo I tried - just did not move, as if it was broken. I guess the shape of the signal is critical for digital servos, I never read this anywhere. Or maybe its something else I dont know.
As a side note, another weirdness I spent a bunch of time on - I uncommented the TIMSK1 = (1 << TOV1); line, thinking I always needed it - but what happened, my main function would get frozen, blocked forever upon first call to delay_ms(...) not sure what it is - but keeping it commented out unblocks my main loop (where I read the servo positin values from the USB HID using Teensy's sample code)
Again, many thanks for the help.

#define PORTX.x in Avr Studio 5 (ATmega16)

I'm writing a new and special library whith new algorithms and abilities for KS0108 GLCD Driver. I'm using ATMega16. My dot matrix GLCD dimension is 128x64.
How can I use #define code to define different port pins?
for example: #define GLCD_CTRL_RESTART PORTC.0
IDE: AVR Studio 5
Language: C
Module: 128x64 dot matrix GLCD
Driver: KS0108
Microcontroller: ATMega16
Please explain which headers I should use? and also write a full and very simple code for ATMEga16.
In ATmega, pin values are assembled in PORT registers. A pin value is the value of a bit in a PORT. ATmega doesn't have a bit addressable IO memory like some other processors have, so you cannot refer to a pin for reading and writing with a single #define like you suggest.
What you can do instead, if it helps you, is to define macros to read or write the pin value. You can change the name of the macros to suit your needs.
#include <avr/io.h>
#define PORTC_BIT0_READ() ((PORTC & _BV(PC0)) >> PC0)
#define WRITE_PORTC_BIT0(x) (PORTC = (PORTC & ~_BV(PC0)) | ((x) << PC0))
uint8_t a = 1, b;
/* Change bit 0 of PORTC to 1 */
WRITE_PORTC_BIT0(a);
/* Read bit 0 of PORTC in b */
b = PORTC_BIT0_READ();
thanks a lot, but i found this answer in AVR Freaks at here:
BV=Bit Value.
If you want to change the state of bit 6 in a byte you can use _BV(6) which is is equivalent to 0x40. But a lot us prefer the completely STANDARD method and simply write (1<<6) for the same thing or more specifically (1<<<some_bit_name_in_position_6)
For example if I want to set bit 6 in PORTB I'd use:
Code:
PORTB |= (1 << PB6);
though I guess I could use:
Code:
PORTB |= _BV(6);
or
Code:
PORTB |= _BV(PB6);
But, like I say, personally I'd steer clear of _BV() as it is non standard and non portable. After all it is simply:
Code:
#define _BV(n) (1 << n)
anyway.
Cliff

Resources