I have a word that I wish to trigger on pin change:
: example
." Hello, world! "
;i
I am using External Interrupt Request 1, which is interrupt vector no. 3 according to page 65 of the datasheet and this diagram I use.
' example 3 int!
ei
When I try to change the value of a pin (pin 3 in this case), nothing happens.
Am I doing something wrong?
There are several things wrong with the code I posted above, but I did get it working after looking at other examples and reading the data sheet:
\ Pin Change Interrupt 0
4 constant pcint0
\ Pin Change Mask Register 0
$6b constant pcmsk0
\ Pin Change Interrupt Control Register
$68 constant pcicr
ram variable example
: example+1
1 example +!
;i
: int-enable
['] example+1 pcint0 int!
ei
;
int-enable
%00000001 pcmsk0 mset
%00000111 $68 mset
\ Shorting pin 8 will now increment `example` variable.
Related
I want to use a RTC from Epson, Model: R4543. I found some Arduino librarys and I want to transform them into Microchip Studio. The original Arduino Code is:
digitalWrite(_dataPin,(data >> i) & 0x01);
and I transformed it in:
PORTC |= (((data>>i)&0x01)<<_dataPin);
is this correct? It does not work, and I'm trying to find the problem.
The type of data is uint8_t.
Thank you,
Markus
It isn't correct. There is wrong two things.
digitalWrite setup pin to value 0 or 1. PORTC |= can set pin value only to 1, not to 0 if pin value is 1.
_dataPin value can by more then 7. DigitalWrite make transformation to port address and bit position. You can make manual transformation like this. And than set pin to 0 or 1 by simple if construction. Assigned values for DATA_PORT and DATA_PIN is illustrative only. You do not provide value of _dataPin variable.
#define DATA_PORT PORTC //maybe not right port name
#define DATA_PIN 0 //maybe not right pin number
if ((data >> i) & 0x01) {
DATA_PORT |= (1<<DATA_PIN);
} else {
DATA_PORT &= ~(1<<DATA_PIN);
}
I've been trying to turn on LED6 on my STM32F407VG Discovery board but for some reason it will not turn on.
My code looks like this:
int main(void)
{
//PD 15
RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN;
GPIOD->MODER |= GPIO_MODER_MODER15_0;
GPIOD->OTYPER &= ~(GPIO_OTYPER_OT_15);
GPIOD->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR15;
GPIOD->PUPDR &= ~(GPIO_PUPDR_PUPDR15);
GPIOD->BSRRH = GPIO_BSRR_BS_15;
return 0;
}
I am using Attolic True studio. When i run the debugger the registers all have the correct looking values in them. The only LEDs that light up are LED1 and LED2 - the power indicator.
Any help would be very much appreciated.
Kind regards
Look like correct but, as I remember stm32f4xx.h has no BSRRH and BSRRL registers (at least last versions) register named as BSRR. Please try to replace the last row to:
GPIOD->ODR |= GPIO_ODR_OD15;
If this code will work, this means you were set incorrect value to BSRRH or need use BSRRL register.
I'm new to simulation on Proteus using microcontroller. All the online beginners tutorial show how to flash LEDs using microcontrollers, I'm just curious cannot we just add two numbers and get the result as output without involving any LED?
Should I just write the adding integers code in C, convert to hex file and load it on ATMEGA328 ? Where (any particular port of the microcontroller) will I see the output? Do I need to specify that in that C code? Please guide me! And also any link doing this kindof stuff would be very helpful.Thanks!!
I think this question is wrong,Please provide enough details
Controller (AVR/PIC/ARM/TI)
8-bit/16-bit/32-bit
Compiler/IDE
In micro controllers you write any port(GPIO) and check your output.
If you don't want to see output with any output device led,7-segment,LCD display and etc then just write port directly and find your answer.
int main()
{
int x=10,y=20;
SET_PORT_DIRECTION = OUTPUT;
YOUR_CONTROLLER_PORT = x+y;
while(1);
}
In Proteus you will find which one YOUR_PORT led is on or off accordingly your output
if you used 8bit Microcontroller
You will able to write MAX Value 255 to the single port(in case of 8-bit micro controller)
X = 10, Y=20;
Then X+Y = 30;
HEX VALUE of 30 : 0x1E;
YOUR_PORT(8 bit) = 0 0 0 0 0 0 0 0;
YOUR_PORT = x+y;
YOUR_PORT = 0 0 0 1 1 1 1 0;
In Proteus
PORT_LED on/OFF :
LHB :
PIN : 0 STATE: OFF
PIN : 1 STATE: ON
PIN : 2 STATE: ON
PIN : 3 STATE: ON
PIN : 4 STATE: ON
PIN : 5 STATE: OFF
PIN : 6 STATE: OFF
PIN : 7 STATE: OFF
and also just used Digital Multi meter to check voltage on controller pins and check your answers.
I have a small 3.5ch USeries helicopter controlled by an IR remote control, using an Arduino I have decoded its 32 bit protocol. Except for last 3 bits which appear to be some form of checksum. As I have successfully decoding the channels from the remote, in that they track their corresponding controls, I can see that slight changes in the controls yield specific changes in the 3 bits, that are very reproducible and deterministic. Whereas I have not yet found a common theme or formal to reproduce the supposed checksum. I have tried simple things like Parity or Added Checksum. I can see the effects of changing specific bits on the cksum but when I combine the changes they don't simply add to the 3 bit value.
struct Useries // bit structure recieved from 32 bit IR command
{
unsigned cksum : 3; // 0..2
unsigned Rbutton : 1; // 3
unsigned Lbutton : 1; // 4
unsigned Turbo : 1; // 5
unsigned Channel : 2; // 6,7
unsigned Trim : 6; // 8..13
unsigned Yaw : 5; // 14..18
unsigned Pitch : 6; // 19..24
unsigned Throttle : 7; // 25..31
};
So the question is "How can I determine the formula for the chksum?" or what ever it is, as to program a recreation of it.
As it appears deterministic one should be able to take the recorded output of cksum and the other 27 bits and derive a formula for it. Much like PLD logic. Whereas the stimuls being 2^27 bit or 128M possibilities, versus the output being only 2^3 or 8 I would suspect even a small sample of <1% or less would provide the formula.
Another way, Is to look at it as a crypto problem and the 3 bit cksum is a hash.
Either way. Any methods or guidance as to determine the solution is greatly appreciated.
Here is sample data
FYI - The USeries is not the Syma. The Syma's decode does not have a cksum. Once I get the USeries chksum determined I will open source them from a fork of Ken Shirriff.
Just FYI
Struct SymaR5// bit structure recieved from 32 bit IR command
{
unsigned Trim : 8; // 0..7 0x7F
unsigned Throttle : 7; // 8..15 0x7F
unsigned Channel : 1; // 16 0x01
unsigned Pitch : 8; // 17..24 0x7F
unsigned Yaw : 8; // 25..31 0x7F
};
A quick check on parity masks results in seven masks that always give parity zero on your data. (Two of your bits are always the same, so I made an assumption about regularity in the mask to eliminate some contenders.) The masks are:
0x2e5cb972
0x5cb972e5
0x72e5cb97
0x972e5cb9
0xb972e5cb
0xcb972e5c
0xe5cb972e
Any of these masks anded with any of your data values (all 32 bits) results in parity zero. Three can be considered special, since each of your identified parity bits occurs just once respectively in those three (the ones ending in 2, 9, and c). So those three masks without the last three bits can be used to get each of the parity bits.
The mask repeats these seven bits: 0010111. This C code uses shifts and exclusive-ors to apply the mask and parity calculation:
p = x;
while ((x >>= 7) != 0)
p ^= x;
p = (p ^ (p >> 1) ^ (p >> 2) ^ (p >> 4)) & 7;
where x and p are 32-bit unsigned types. x is the 32 bits received. If p is zero when done, then the received value is good.
I'm having trouble getting a rotary encoder to work properly with AVR micro controllers. The encoder is a mechanical ALPS encoder, and I'm using Atmega168.
Clarification
I have tried using an External Interrupt to listen to the pins, but it seems like it is too slow. When Pin A goes high, the interrupt procedure starts and then checks if Pin B is high. The idea is that if Pin B is high the moment Pin A went high, then it is rotating counter clock-wise. If Pin B is low, then it is rotating clock-wise. But it seems like the AVR takes too long to check Pin B, so it is always read as high.
I've also tried to create a program that simply blocks until Pin B or Pin A changes. But it might be that there is too much noise when the encoder is rotated, because this does not work either. My last attempt was to have a timer which stores the last 8 values in a buffer and checks if it is going from low to high. This did not work either.
I have tried scoping the encoder, and it seems to use between 2 and 4ms from the first Pin changes till the other Pin changes.
I have a webpage about rotary encoders and how to use them, which you might find useful.
Unfortunately without more information I can't troubleshoot your particular problem.
Which microcontroller pins are connected to the encoder, and what is the code you're currently using to decode the pulses?
Ok, you're dealing with a few different issues, the first issue is that this is a mechanical encoder, so you have to deal with switch noise (bounce, chatter). The data sheet indicates that it may take up to 3mS for the parts to stop bouncing and creating false outputs.
You need to create a debounce routine. The simplest of which is to continuously check to see if A goes high. If it does, start a timer and check it again in 3 ms. If it's still high, then you can check B - if it's not high then you ignore the spurious pulse and continue looking for A high. When you check B, you look at it, start a timer for 3 ms, and then look at B again. If it was the same both times, then you can use that value - if it changes within 3 ms then you have to do it again (read B, wait 3 ms, then read it again and see if it matches).
The atmega is fast enough that you shouldn't have to worry about these checks going slowly, unless you're also running a slow clock speed.
Once you deal with the mechanical noise, then you want to look at a proper gray code routine - the algorithm you're following won't work unless you also decrement if A is high when B goes low. Generally people store the last value of the two inputs, and then compare it to the new value of the two inputs and use a small function to increment or decrement based on that. (Check out the heading "high resolution reading" on the website I mentioned above for the table). I combine the two readings into a four bit number and use a simple array to tell me whether I increment or decrement the counter, but there are solutions that are even more advanced, and optimize for code size, speed, or ease of code maintenance.
Adding an analog lowpass filter greatly improves the signal. With the lowpass filter, the code on the AVR was really simple.
_________
| |
| Encoder |
|_________|
| | |
| | |
100n | O | 100n
GND O-||-+ GND +-||-O GND
| |
\ /
3K3 / \ 3K3
\ /
| |
VCC O-/\/-+ +-\/\-O VCC
15K | | 15K
| |
O O
A B
Ah, the wonders of ASCII art :p
Here is the program on the AVR. Connect A and B to input PORTB on the avr:
#include <avr/io.h>
#define PIN_A (PINB&1)
#define PIN_B ((PINB>>1)&1)
int main(void){
uint8_t st0 = 0;
uint8_t st1 = 0;
uint8_t dir = 0;
uint8_t temp = 0;
uint8_t counter = 0;
DDRD = 0xFF;
DDRB = 0;
while(1){
if(dir == 0){
if(PIN_A & (!PIN_B)){
dir = 2;
}else if(PIN_B & (!PIN_A)){
dir = 4;
}else{
dir = 0;
}
}else if(dir == 2){
if(PIN_A & (!PIN_B)){
dir = 2;
}else if((!PIN_A) & (!PIN_B)){
counter--;
dir = 0;
}else{
dir = 0;
}
}else if(dir == 4){
if(PIN_B & (!PIN_A)){
dir = 4;
}else if((!PIN_A) & (!PIN_B)){
counter++;
dir = 0;
}else{
dir = 0;
}
}else if(PIN_B & PIN_A){
dir = 0;
}
PORTD = ~counter;
}
return 0;
}
This code works unless you rotate the encoder really fast. Then it might miss a step or two, but that is not important, as the person using the encoder won't know how many steps they have turned it.
Speed should not be a problem. Mostly all mechanical switches need debounce routines. If you wanna do this with interrupts turn off the interrupt when it triggers, start a timer that will turn it back on after a couple of ms. Will keep your program polling-free >:)
What exactly are you having problems with? I assume you've been able to hook the pins of the encoder to your PIC as per the technical specifications linked on the Farnell page you gave, so is the problem with reading the data? Do you not get any data from the encoder? Do you not know how to interpret the data you're getting back?
/* into 0 service rutine */
if(CHB)
{
if(flagB)
Count++;
FlagB=0;
}
else
{
if(FlagB)
count--:
FlagB=0:
}
/* into 1 service rutine */
FlagB=1;
/* make this give to you a windows time of 1/4 of T of the encoder resolution
that is in angle term: 360/ (4*resolution)
*/