I'm programming an Intel 8051 (C8051F312) microcontroller. I just want to make a blinking led program by using interrupts. It compiles, but the led does not blink. Any ideas I would appreciate. Thank you!
My code is:
#include <C8051F310.H>
#include <stdio.h>
sbit led = P2^7; //LED connected to D7 of Port2
void timer(void) interrupt 1 //interrupt no. 1 for Timer 0
{
led=~led; // toggle LED on interrupt
TH0=0xFC; // initial values loaded to timer
TL0=0x66;
}
void main(void)
{
TMOD = 0x01; // mode1 of Timer0
TH0 = 0xFC; // initial values loaded to timer
TL0 = 0x66;
EA = 1; // global interrupt enable
ET0 = 1; // enables Timer 0 interrupt
TR0 = 1; // start timer
while(1); // do nothing
}
Like Mike Jablonski above said, you need to knock down your interrupt rate. Your original code is interrupting at 3.0625MHz / 12 / 922 ~= 277Hz. Part of your CKCON addition disables scaling to the timer (by setting T0M), so now you're interrupting at ~3.3kHz. You won't be able to see that.
Seeing anything presumes that you have a functional circuit. You're not configuring your output pin. You said your LED is on "now", but hopefully not meaning that it wasn't before. That wouldn't make a lot of sense since you didn't change anything about what the pin is doing.
Get rid of your CKCON line to keep the /12 scaling, and reload TH0 and TL0 with 0x00 on interrupt. That will get you interrupting at a little less than 4Hz, much more visible.
Make that pin push-pull:
P2MDOUT = 0x80;
XBR1 = 0x40;
Start reading the datasheet to your micro.
Related
I am developing a simple program to run a buzzer in AVR on a Teensy 2.0 (ATMEGA32u4) and I am having great difficulty getting the PWM output to work. The PWM output is on PB6 and I can test it digitally so I am not worried about the hardware setup of the buzzer.
Eventually, the PWM will have a 50% duty cycle and the frequency will modulate, however, I am more concerned I am not getting any output at this point.
I have tried several different PWM setups and even have a second timer running to complete other tasks.
Here is my setup and program skeleton:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
void button_handler(void);
void setup(void)
{
cli(); // Disable interrupts
// Set sysclk to 16 MHz
CLKPR = (1<<CLKPCE); // Prescaler change enable
CLKPR = 0x00; // Set prescaler to zero
DDRB = (1<<DDB6); // configure PORT B6 (buzzer) as output
// initliase timer1
// Fast PWM, TOP = OCR1A, Update OCR1B at TOP, TOV1 flag set on TOP
// Clear OC1B on compare match, set OC1B at TOP
// clkI/O/1 (No prescaling)
TCCR1A = (1<<COM1B1)|(1<<WGM11)|(1<<WGM10);
TCCR1B = (1<<WGM13)|(1<<WGM12)|(1<<CS10);
OCR1A = 1023; // Setup PWM Registers
OCR1B = 511; // 50% duty cycle
sei(); // Enable interrupts
}
int main(void)
{
setup(); // initialise device
for (;;)
{
// runs led blinking on PORTD, removed for simplicity
}
}
Really struggling to see where I am going wrong so any help would be much appreciated!
Finally managed a fix coming back after a few months, a simple clean fixed the issue.
I am currently working on a low-power project using the Adafruit Feather M0 microprocessor. A requirement of my project is to be able to sleep the CPU and wake it again using an external interrupt triggered from the MPU6050 accelerometer.
I have tested the following code sample from GitHub - it works successfully! The question that I need answering is how to I alter this sample code to work on Pin 13 of the feather, rather than pin 6.
#define interruptPin 6
volatile bool SLEEP_FLAG;
void EIC_ISR(void) {
SLEEP_FLAG ^= true; // toggle SLEEP_FLAG by XORing it against true
//Serial.print("EIC_ISR SLEEP_FLAG = ");
//Serial.println(SLEEP_FLAG);
}
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
delay(3000); // wait for console opening
attachInterrupt(digitalPinToInterrupt(interruptPin), EIC_ISR, CHANGE); // Attach interrupt to pin 6 with an ISR and when the pin state CHANGEs
SYSCTRL->XOSC32K.reg |= (SYSCTRL_XOSC32K_RUNSTDBY | SYSCTRL_XOSC32K_ONDEMAND); // set external 32k oscillator to run when idle or sleep mode is chosen
REG_GCLK_CLKCTRL |= GCLK_CLKCTRL_ID(GCM_EIC) | // generic clock multiplexer id for the external interrupt controller
GCLK_CLKCTRL_GEN_GCLK1 | // generic clock 1 which is xosc32k
GCLK_CLKCTRL_CLKEN; // enable it
while (GCLK->STATUS.bit.SYNCBUSY); // write protected, wait for sync
EIC->WAKEUP.reg |= EIC_WAKEUP_WAKEUPEN4; // Set External Interrupt Controller to use channel 4 (pin 6)
PM->SLEEP.reg |= PM_SLEEP_IDLE_CPU; // Enable Idle0 mode - sleep CPU clock only
//PM->SLEEP.reg |= PM_SLEEP_IDLE_AHB; // Idle1 - sleep CPU and AHB clocks
//PM->SLEEP.reg |= PM_SLEEP_IDLE_APB; // Idle2 - sleep CPU, AHB, and APB clocks
// It is either Idle mode or Standby mode, not both.
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; // Enable Standby or "deep sleep" mode
SLEEP_FLAG = false; // begin awake
// Built-in LED set to output and high
PORT->Group[g_APinDescription[LED_BUILTIN].ulPort].DIRSET.reg = (uint32_t)(1<<g_APinDescription[LED_BUILTIN].ulPin); // set pin direction to output
PORT->Group[g_APinDescription[LED_BUILTIN].ulPort].OUTSET.reg = (uint32_t)(1<<g_APinDescription[LED_BUILTIN].ulPin); // set pin mode to high
Serial.println("Setup() Run!");
}
void loop() {
// put your main code here, to run repeatedly:
if (SLEEP_FLAG == true) {
PORT->Group[g_APinDescription[LED_BUILTIN].ulPort].OUTCLR.reg = (uint32_t)(1<<g_APinDescription[LED_BUILTIN].ulPin); // set pin mode to low
Serial.println("I'm going to sleep now.");
__WFI(); // wake from interrupt
SLEEP_FLAG = false;
Serial.println("Ok, I'm awake");
Serial.println();
}
//Serial.print("SLEEP_FLAG = ");
//Serial.println(SLEEP_FLAG);
PORT->Group[g_APinDescription[LED_BUILTIN].ulPort].OUTTGL.reg = (uint32_t)(1<<g_APinDescription[LED_BUILTIN].ulPin); // toggle output of built-in LED pin
delay(1000);
}
As per the pinout diagram and Atmel datasheet, I am struggling to work out which changes to make to allow pin 13 to operate in the same way as pin 6.
Atmel Datasheet
The obvious solution is to change the following lines...
#define interruptPin 13
EIC->WAKEUP.reg |= EIC_WAKEUP_WAKEUPEN1; // Set External Interrupt Controller to use channel 4 (pin 6)
I suspected channel 1 (WAKEUPEN1) due to the ENINT^1 next to pin 13 on the pinout diagram. But this didn't work, the code pin operation did not exhibit the same behaviour as the pin 6 setup.
I would be very grateful for any suggestion of how to implement this code working on Pin 13. Many thanks for your support.
I'm not an authority here, and your code looks correct to me.
Except, the pin out shows Pin 13 is the built-in LED line, and you manipulate LED_BUILTIN several places in your code. That's almost certainly conflicting with your attempts to use 13 as an interrupt line.
I'm new to PIC programming and I'm using MPLAb. I have a question regarding interrupt..
so What I want to do, when I push a button then I want to turn on LED 0, and if I release the button then turn on LED 1. I thought the code I wrote making sense but it didn't work.
Here is what happens. Let say the initial state of interrupt pin is low (0), when a button is pushed. Then the LED 0 is on, and when I release the button then LED 1 is on. When I push the button again, I expect LED 0 is on, but LED 1 stays on, and never change the state.
I added last line to see the state of interrupt pin, and once the interrupt is high, it never change it to low.. Can you please advise me what is my misunderstanding?
Thanks in advance!
Here is my code:
void interrupt ISR(void)
{
if(INTCONbits.INTF)
{
nextLED = 1;
LATC = Output_Code_Buffer[nextLED];
__delay_ms(250);
}
else
{
nextLED = 0;
LATC = Output_Code_Buffer[nextLED];
__delay_ms(250);
}
nextLED = INTCONbits.INTF + 2;
LATC = Output_Code_Buffer[nextLED];
__delay_ms(250);
}
// Interrupt Enable settings
INTCONbits.INTE = 1;
INTCONbits.TMR0IE = 1; // Enable TMR0 interrupts
INTCONbits.TMR0IF = 0; // Clear TMR0 interrupt flag
INTCONbits.GIE = 1; // Enable global interrupts
You need to reset the interrupt flag in the ISR function or it will just keep triggering. Please read the datasheet, it should mention if this is necessary. So just add INTCONbits.INTF = 0; to the ISR and it should work as expected.
When setting up any peripheral or function of the mcu, you should go through the datasheet and use the description of the registers and what to set them. You'll also need to be careful with analogue ports, which often default to analogue instead of digital, causing interrupt not to fire as expected or causing unexpected interrupts. It's best to first setup the MCU config bits, set the TRIS and analogue selection registers (ANSELx or ANSELAx etc), then the registers for any peripheral you want to use. Then setup the interrupts, always reset all the interrupt flags you're going to use to start with a known state.
You also set TMR0IE = 1, which will do the same thing, trigger an interrupt. If you don't reset the TMR0 flag it will keep triggering, locking up your mcu or slow it down.
So I'm having a problem getting a TI microcontroller to communicate with the Raspberry Pi B+. The exact microcontroller I'm using is the TI cc430f5137. The issue I'm having is that I just can't seem to get the Raspberry Pi to correctly receive the data I'm sending from the MSP430. For those who don't know, the 430 has 2 buffers for this purpose, a RX and TX, which allows the use of the UART module while code is still executing. I've enabled an interrupt for when I receive a byte, and I simply set a flag and send the same byte right back. It works up until I attempt to transmit.
The code sits and waits in an infinite loop until it receives it's first byte. At that point it simply saves the byte and flashes the LED if it's a 'T' (for testing). Upon returning to the loop, it detects that the saved byte has changed, and puts it in the buffer to send it back. Until this point, everything works perfectly. It receives the correct byte every time, letting me know my clocks are perfect, my interrupt is working, and my UART initialization is correct. Where it goes wrong is after sending the byte, it seems like there is some kind of internal loopback (this is an option but I made sure this is not the case) that is causing the interrupt to re-trigger, resulting in an infinite loop of transmitting and again receiving the same byte, but upon invoking this via the Pi I don't get back a loop of the same character, but instead a byte of random garbage that has no consistency or logic behind it. I analyzed the bits to see if the timing is just off and that doesn't seem to be the case. For reference, my Baud is a measly 1200, the voltage of both devices is definitely 3.3v, and I'm sure the Pi is working because when I short the RX and TX, I get back the byte without an issue. I switched to UART because SPI was giving me similar problems, and I can't think of any other protocol besides I2C that would help here. I am using an external 32768hz crystal. Also, I've tried this on two different microcontrollers, so its definitely the code that's the issue.
#include <msp430.h>
char temp;
char in;
int main(void) {
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
P1OUT = 0x00; // Make sure pins are tturned off
P1DIR = 0x01; // Led out
P1SEL |= BIT5 + BIT6; // UART as pin mode
UCSCTL6 &= ~BIT0; // Turn on XT1
P5SEL |= BIT0 + BIT1; // Select XT1 as pin function
UCA0CTL1 |= BIT0; // Set UART to reset mode
UCA0CTL1 |= BIT6; // Choose ACLK as source
UCA0BR0 = 27; // Set speed to 1200 Baud
UCA0MCTL = 0x02 << 1; // Set speed to 1200 Baud
UCA0CTL1 &= ~BIT0; // Turn UART on
UCA0IE = BIT0; // Enable RX interrupt
__enable_interrupt();
while(1)
{
if(in != 0)
{
UCA0TXBUF = in;
temp = in;
in = 0;
}
}
}
#pragma vector=USCI_A0_VECTOR
__interrupt void UCSIA0(void)
{
in = UCA0RXBUF;
if(in == 0x54)
P1OUT ^= BIT0;
}
Output from running minicom at 1200 on Pi, Sending 'T' one at a time:
UÔÿÿïÕuU_þýÿÿÿÿÿÿÕԯÿÿôÕüÿÝUõï\þþÿÿÕ¿ÿÿýýTÿýUÿÿÿïÿÿÿõÿýýÿõûÿ
assuming Pi is working currectly...
1.verify msp430 TX is woring: send every 1 sec known value and see if PI getting it currectly.
2.verify MSP430 RX working: send from Pi known value every 1 sec.
3.interrupt section:
your code dosent verfiy that RX interrupt is off.
you should filter interrupts generated only for the RX .
also, your code dont handle overrun/frame errors.
sharing "in" variable both for TX and RX (and both at interrupt and main loop section)-not good idea..
4.your output example suggests that you have baud rate mismatch issue.
if you send character 'T' and shoud get back 'T'. i expect to see 'TTTTTT...'
BTW this garbage may suggests that you forgot to connecting GND line between two MCUs...
I am trying to get an Arduino UNO to read a 64cpr quadrature encoder. I specifically want to use Timer1 to measure of the frequency (and hence speed) of one of the encoder signals.
I ultimately want to store 10 measurements in an array to compute a moving average filter, but one thing at a time. I first need to be able to measure the clock cycles between two rising edges.
Here's what I've got so far. Any help or comments are appreciated:
#include <avr/io.h>
#include <avr/interrupt.h>
const int inputCapture = 8;
void setup(){
sei();
TCNT1 = 0;
TCCR1B = (1<<CS10)|(1<<ICES1); // No prescaling
TIFR1 = 1<<ICF1;
pinMode(inputCapture, INPUT);
Serial.begin(9600);
}
ISR(TIMER1_CAPT1_vect){
thisStep = ICR1;
TCNT1 = 0;
}
void loop(){
Serial.println(thisStep);
}
Right now I'm not even jumping into the ISR, which I don't understand. I think I have set everything up correctly. Interrupts are enabled. ICES1 should default to 0, or falling edge trigger, which is fine (just want to measure one period). I'm picking a pin on port B to receive the (input) signal, which should be fine. From Atmel's documentation, I think Timer1 is connected.
Any thoughts? Thanks in advance!