This question already has answers here:
How to set and clear different bits with a single line of code (C)
(2 answers)
Closed 6 years ago.
I recently started learning about the IAR embedded workbench 8051. Well, I am currently playing with the LED only. I am using CC2540 BLE chip to do this. Let's say I have 8 pins of LED but I only want to control only 2 pins by not affect other 6 pins, how to code it using bitwise operators? I set all the pin for GPIO using this code P1SEL = 0;, my friend told me if I type the code like this will affect others pins. What if I declare it P1SEL = 0xFC;? Will others pin be affected?
Actually, you can use & and | to set a specific bit.
P1SEL = P1SEL & (~(1 << i)) // set bit i to 0
P1SEL = P1SEL | (1 << i) // set bit i to 1
Related
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.)
I tried to create a CTC timer interrupt on my ATmega32U4 leonardo board. When I continuously check the value of OCF1A I have no problem detecting when the output reaches the desired value, however once I move the code into an interrupt, the interrupt never triggers.
Timer setup:
#include <avr/io.h>
void setupTimer()
{
TCCR1B |= (1 << WGM12); // CTC mode
TCCR1B |= ((0 << CS10) | (0 << CS11) | (1 << CS12)); // set up prescaler
OCR1A = 6249; // 100 ms set up output compare value for interrupt
TIMSK1 |= (1 << OCIE1A); // enable interrupt on clock compare
}
The loop that works:
setupTimer();
for (;;) {
if (TIFR1 & (1 << OCF1A)) {
PORTC ^= (1 << PORTC7);
TIFR1 = (1 << OCF1A);
}
}
The interrupt that does not work:
#include <avr/interrupt.h>
ISR(TIMER1_COMPA_vect) {
PORTC ^= (1 << PORTC7);
}
I must be missing something as from what I have seen in the tutorials the above code should work. One interesting observation here is that if I have both the loop and the interrupt in my code at once if I call sei(), the LED does not blink as if the OCF1A register was cleared prematurely.
I'm pretty sure it is irrelevant in this case but the fuses are as follows: E:CB, H:D8, L:FF.
I use avr-g++ to compile and the code is spread out between several files.
Given that someone got here through google two years after this question was asked I suppose I should share my own findings on this matter.
The code provided in my question is correct and assuming that there is a call to sei()somewhere after the setupTimer() the interrupt should trigger correctly. The issue was just as c0redumb described in his answer - the bootloader was messing with some registers and thus preventing the code from running correclty. However my solution to this problem was slightly different as in my case, the interrupt would not trigger even after unplugging and re-plugging the board (it is possible that the bootloader has changed in the two years since I have asked this question).
The simplest way to prevent a conflict between the code and the bootloader is to simply remove the bootloader. By using USBasp programmer one can simply load their own code onto the board and thus be sure that it is the only thing running on the CPU.
You have two problems:
You need to make sure main() doesn't return even when it's not doing anything except waiting for the interrupt
You need to enable interrupts via sei() after setting everything up.
Here's a working example (I changed the LED port to PB5 because I've tested this on an Arduino Uno and that already has an LED built-in)
#include <avr/interrupt.h>
#include <avr/io.h>
void main ()
{
DDRB |= 1 << DDB5;
TCCR1B |= 1 << WGM12;
TCCR1B |= 1 << CS12;
OCR1A = 6249;
TIMSK1 |= 1 << OCIE1A;
sei();
for(;;);
}
ISR(TIMER1_COMPA_vect)
{
PORTB ^= 1 << PORTB5;
}
This issue puzzles me today as well. Through search I found your question. I did some more searches all around and found no answer to this one. I had thought that I must have forgotten to enable some circuit or set some flags. Finally, with an LED as my debugger, I have found the cause.
The problem is with the bootloader, not your code. To get it to work, you just unplug the board from USB (after having written code through bootloader), and re-plugin so the bootloader jumps directly to your code at powerup, and it works there. The bootloader must have done some fancy footwork in uploading the code, and didn't work all well afterward in this situation.
As a reference, I used a ProMicro board which I believe has Caterina bootloader same as the Leonardo board you used.
I am currently programming raspberry pi.
I wanted to get clear out some doubts, please can anybody help.
Here is the code snippet.
#define GPIO_BASE 0x20200000UL
gpio = (unsigned int*)GPIO_BASE; gpio[GPIO_GPFSEL1] |= (1 << 18);
This code is from http://www.valvers.com/embedded-linux/raspberry-pi/step01-bare-metal-programming-in-cpt1
I do understand the functionality of the code to switch on and switch off the LED .
I have problem understand the these statements
gpio = (unsigned int*)GPIO_BASE; gpio[GPIO_GPFSEL1] |= (1 << 18);
First you have some address in memory.
define GPIO_BASE 0x20200000UL
Under this address exists a control structure for GPIO. In your case it's just an array of ints. Writing a value to a certain field of that structure makes GPIO set its pins.
gpio = (unsigned int*)GPIO_BASE;
You select some register in your structure (the address (unsigned int*)GPIO_BASE + GPIO_GPFSEL1) and you set the 18th bit on.
gpio[GPIO_GPFSEL1] |= (1 < < 18);
The GPIO will likely respond with setting one of its pins to high state. The LED attached to that pin will start glowing.
Well ...
The first statement:
gpio = (unsigned int*)GPIO_BASE;
sets the pointer variable gpio equal to the value of GPIO_BASE, and also casts the latter to a pointer type.
The second
gpio[GPIO_GPFSEL1] |= (1 << 18);
does a bitwise OR of the value in gpio[GPIO_GPFSEL1] with the constant value 1 << 18. This "turns on" bit 18 (counting from 0) in the register GPIO_GPFSEL1.
Remember that in C, array indexing a[b] is the same as *(a + b), i.e. it's a pointer addition and dereferencing.
After
gpio = (unsigned int*)GPIO_BASE;
gpio points to 0x20200000 memory address. This is "The base address of the GPIO peripheral (ARM Physical Address)".
Article that you've linked says that:
Back to the processor manual and we see that the first thing we need
to do is set the GPIO pin to an output. This is done by setting the
function of GPIO16 to an output. Bits 18 to 20 in the ‘GPIO Function
Select 1′ register control the GPIO16 pin.
Statement
#define GPIO_GPFSEL1 1
gpio[GPIO_GPFSEL1] |= (1 << 18);
breaks down to:
gpio[1] = gpio[1] | (1 << 18);
So, address (0x20200000 + sizeof(unsigned int)) is dereferenced and OR operator sets the bit 18 to 1.
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.
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