ISR not execute in rs484 with msp430fg6626 in receiving mode - css

Why code stucked in the ISR routine in msp430fg6626 microcontroller? here i performing the rs485 communiction with this uc and SN75176A max485 ic.during this i was set the buad rate at 9600 here data was successfully sent from uc and same received at the max485 ic but in receiving time data was not received at uc from max485 ic. why this occured i will share the code of same here please check and answer me.
i will share the samw code below
code was stuck in this line -> __bis_SR_register(LPM3_bits + GIE);
#include <msp430.h>
int ReceiveData;
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // Stop WDT
CTSD16CCTL0 |= CTSD16SC; // Workaround for CTSD16OFFG errata
do
{
CTSD16CTL &= ~CTSD16OFFG;
}
while (CTSD16CTL&CTSD16OFFG); // End of CTSD16OFFG workaround
while(BAKCTL & LOCKBAK) // Unlock XT1 pins for operation
BAKCTL &= ~(LOCKBAK);
UCSCTL6 &= ~(XT1OFF); // XT1 On
UCSCTL6 |= XCAP_3; // Internal load cap
// Loop until XT1 fault flag is cleared
do
{
UCSCTL7 &= ~(XT2OFFG | XT1LFOFFG | DCOFFG);
// Clear XT2,XT1,DCO fault flags
SFRIFG1 &= ~OFIFG; // Clear fault flags
}while (SFRIFG1&OFIFG); // Test oscillator fault flag
//------------ Configuring MAX485 Control Lines ---------------//
P8SEL |= BIT4; // Assign P8.4 to ~RE DE and...
P8DIR |= BIT4; // P8.4 -> DE,-> ~RE output
P8OUT &= ~(BIT4); // ~RE & DE SET TO ZERO IN RECEIVING MODE
P8SEL |= 0x0C; // Assign P8.2 to UCA0TXD and...
P8DIR |= 0x0C; // P8.3 to UCA0RXD
UCA1CTL1 |= UCSWRST; // **Put state machine in reset**
UCA1CTL1 |= UCSSEL_1; // CLK = ACLK
UCA1BR0 = 0x03; // 32kHz/9600=3.41 (see User's Guide)
UCA1BR1 = 0x00; //
UCA1MCTL = UCBRS_3|UCBRF_0; // Modulation UCBRSx=3, UCBRFx=0
UCA1CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
UCA1IE |= UCRXIE; // Enable USCI_A1 RX interrupt
__bis_SR_register(LPM3_bits + GIE); // Enter LPM3, interrupts enabled***
__no_operation(); // For debugger
while(1)
{
while (!(UCA1IFG&UCTXIFG)); // USCI_A1 TX buffer ready?
// UCA1TXBUF = 0x55; // TX -> RXed character
// __delay_cycles (160000);
}
}
// Echo back RXed character, confirm TX buffer is ready first
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=USCI_A1_VECTOR
__interrupt void USCI_A1_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_A1_VECTOR))) USCI_A1_ISR (void)
#else
#error Compiler not supported!
#endif
{
switch(__even_in_range(UCA1IV,4))
{
case 0:break; // Vector 0 - no interrupt
case 2: // Vector 2 - RXIFG
while (!(UCA1IFG&UCTXIFG)); // USCI_A1 TX buffer ready?
ReceiveData=UCA1RXBUF;
P8OUT |= BIT4; // ~RE & DE SET TO HIGH FOR TRANSMITTING MODE
__delay_cycles (16000);
UCA1TXBUF = ReceiveData; // TX -> RXed character
__delay_cycles (16000);
P8OUT |= ~(BIT4); // ~RE & DE SET TO ZERO IN RECEIVING MODE
__delay_cycles (16000);
break;
case 4:break; // Vector 4 - TXIFG
default: break;
}
}

Related

Interrupt-Flag is set although Interrupt-Enable-Flag is not set

i've written a small program for the MSP430FR6989 to toggle the LED as long as the Button is pressed.
#include <msp430.h>
/**
* main.c
*/
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
PM5CTL0 &= ~LOCKLPM5;
// reset port 1
P1DIR = 0x00;
P1OUT = 0x00;
// turn off led on startup
P1DIR |= BIT0;
P1OUT &= ~BIT0;
P1DIR &= ~BIT1; // P1.1 -> input
P1REN |= BIT1; // P1.1 -> enable resistor
P1OUT |= BIT1; // P1.1 -> pull-up resistor
// enable on P1.1
P1IES |= BIT1;
P1IE |= BIT1;
P1IFG = 0x00;
__enable_interrupt();
while(1)
{
__delay_cycles(1000);
}
return 0;
}
#pragma vector=PORT1_VECTOR
__interrupt void PORT1_ISR(void)
{
switch (__even_in_range(P1IV, P1IV_P1IFG1))
{
case P1IV_P1IFG1:
P1OUT = (P1IN & BIT1)
? P1OUT & ~BIT0
: P1OUT | BIT0;
P1IES ^= BIT1;
break;
default:
break;
}
}
Everything works as expected.
BUT: When I debug the program I see that BIT0 in P1IFG is set as soon as I pressed the button for the first time.
Why is this happening? I thought it would only be set if I enable the corresponding IE-Bit?
Thanks in advance
Section 12.2.6 of the MSP430FR58xx, MSP430FR59xx, and MSP430FR6xx Family User's Guide says:
Each PxIFG bit is the interrupt flag for its corresponding I/O pin, and the flag is set when the selected input signal edge occurs at the pin. All PxIFG interrupt flags request an interrupt when their corresponding PxIE bit and the GIE bit are set.
So you can always use the P1IFG bit to check if a transition on the input pin has happened. This is useful if you want to detect short pulses that might already be over when your code gets around to reading the current state of the pin.
This is why you should clear the P1IFG register before enabling interrupts (unless you are interested in old events).

How do I have this audio and LED activate ONLY when a button is held using an Arduino?

I have this code that I am using to play a sound effect where I used a program called wav2c to convert a .wav file to number values that I put into a header file that I use in the code to generate the sound. I currently have it programmed to play the audio upon uploading it to the Arduino with an LED being activated along with it and staying lit for just the duration of the sound effect. I am trying to program it so that the sound and LED only activate when I am pressing a button. I have the pin the button is plugged into already programmed in but I'm not sure how to have it control the audio and LED as stated above. I don't have much experience with programming or Arduino so any help is much appreciated! I am using an Arduino Mega 2560.
The code
#include <stdint.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#define SAMPLE_RATE 20000
#include "Test.h"
int ledPin = 2;
int speakerPin = 9; // Can be either 3 or 11, two PWM outputs connected to Timer 2
const byte pinSwitch1 = 3;
volatile uint16_t sample;
byte lastSample;
void stopPlayback()
{
digitalWrite(ledPin, LOW);
// Disable playback per-sample interrupt.
TIMSK1 &= ~_BV(OCIE1A);
// Disable the per-sample timer completely.
TCCR1B &= ~_BV(CS10);
// Disable the PWM timer.
TCCR2B &= ~_BV(CS10);
digitalWrite(speakerPin, LOW);
}
// This is called at 8000 Hz to load the next sample.
ISR(TIMER1_COMPA_vect) {
if (sample >= sounddata_length) {
if (sample == sounddata_length + lastSample) {
stopPlayback();
}
else {
if(speakerPin==11){
// Ramp down to zero to reduce the click at the end of playback.
OCR2A = sounddata_length + lastSample - sample;
} else {
OCR2B = sounddata_length + lastSample - sample;
}
}
}
else {
if(speakerPin==11){
OCR2A = pgm_read_byte(&sounddata_data[sample]);
} else {
OCR2B = pgm_read_byte(&sounddata_data[sample]);
}
}
++sample;
}
void startPlayback()
{
pinMode(speakerPin, OUTPUT);
// Set up Timer 2 to do pulse width modulation on the speaker
// pin.
// Use internal clock (datasheet p.160)
ASSR &= ~(_BV(EXCLK) | _BV(AS2));
// Set fast PWM mode (p.157)
TCCR2A |= _BV(WGM21) | _BV(WGM20);
TCCR2B &= ~_BV(WGM22);
if(speakerPin==11){
// Do non-inverting PWM on pin OC2A (p.155)
// On the Arduino this is pin 11.
TCCR2A = (TCCR2A | _BV(COM2A1)) & ~_BV(COM2A0);
TCCR2A &= ~(_BV(COM2B1) | _BV(COM2B0));
// No prescaler (p.158)
TCCR2B = (TCCR2B & ~(_BV(CS12) | _BV(CS11))) | _BV(CS10);
// Set initial pulse width to the first sample.
OCR2A = pgm_read_byte(&sounddata_data[0]);
} else {
// Do non-inverting PWM on pin OC2B (p.155)
// On the Arduino this is pin 3.
TCCR2A = (TCCR2A | _BV(COM2B1)) & ~_BV(COM2B0);
TCCR2A &= ~(_BV(COM2A1) | _BV(COM2A0));
// No prescaler (p.158)
TCCR2B = (TCCR2B & ~(_BV(CS12) | _BV(CS11))) | _BV(CS10);
// Set initial pulse width to the first sample.
OCR2B = pgm_read_byte(&sounddata_data[0]);
}
// Set up Timer 1 to send a sample every interrupt.
cli();
// Set CTC mode (Clear Timer on Compare Match) (p.133)
// Have to set OCR1A *after*, otherwise it gets reset to 0!
TCCR1B = (TCCR1B & ~_BV(WGM13)) | _BV(WGM12);
TCCR1A = TCCR1A & ~(_BV(WGM11) | _BV(WGM10));
// No prescaler (p.134)
TCCR1B = (TCCR1B & ~(_BV(CS12) | _BV(CS11))) | _BV(CS10);
// Set the compare register (OCR1A).
// OCR1A is a 16-bit register, so we have to do this with
// interrupts disabled to be safe.
OCR1A = F_CPU / SAMPLE_RATE; // 16e6 / 8000 = 2000
// Enable interrupt when TCNT1 == OCR1A (p.136)
TIMSK1 |= _BV(OCIE1A);
lastSample = pgm_read_byte(&sounddata_data[sounddata_length-1]);
sample = 0;
sei();
}
void setup()
{
pinMode( pinSwitch1, INPUT );
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, HIGH);
startPlayback();
}
void loop()
{
while (true);
}
The header file referenced in the code with the numeric values to create the audio.
#ifndef _HEADERFILE_H // Put these two lines at the top of your file.
#define _HEADERFILE_H // (Use a suitable name, usually based on the file name.)
const int sounddata_length=32000;
//const int sounddata_sampleRate=20000;
const unsigned char sounddata_data[] PROGMEM = {
15,1,49,0,150,0,138,0,219,255,133,0,176,0,15,1,210,
//There are many lines of more numbers in between that I cut out to save space
};
#endif // _HEADERFILE_H // Put this line at the end of your file.
The following changes will allow you to start playback whenever there is a falling edge on your switch pin. You may need to tweak to avoid switch 'bouncing'.
Firstly, add a global variable to record the last switch state:
int lastSwitchState;
Change your setup() to
void setup() {
pinMode(pinSwitch1, INPUT);
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, HIGH);
lastSwitchState = digitalRead(pinSwitch1);
}
and your loop() function to
void loop() {
delay(50);
int switchState = digitalRead(pinSwitch1);
if (switchState != lastSwitchState) {
lastSwitchState = switchState;
if (switchState == LOW) {
startPlayback();
}
}
}
Interrupts vs polling
Instead of polling the switch pin inside the main loop(), you could use interrupts. You would use attachInterrupt() to do this. Interrupts are only available on certain pins, however, and the above approach is conceptually simpler I think.

ERROR SPI on ATmega328P of Arduino

I use SPI on ATmega328 with raw code, data is transferred correctly, but the value return just correct in the second time. I don't know why. I think the data buffer register doesn't update immediately, when I push the button (this is video left is yellow LED, right is red LED: https://drive.google.com/open?id=1bf2XlxRBGCaUo0j2ezB2XFxfSItUmChN and code below)
I use Arduino Uno is a master to send data and get response. Arduino Nano is a slave to receive data and response to master.
Arduino Uno (master) code:
#define DDR_SPI DDRB
#define PORT_SPI PORTB
#define MOSI 3
#define SCK 5
#define SS 2
#define red 2
#define cbi(port, bits) (port) &= ~(1 << (bits))
#define sbi(port, bits) (port) |= (1 << (bits))
volatile uint8_t Data1;
volatile uint8_t Data2;
void setup()
{
Serial.begin(9600); //debug by UART
SPCR = 0; // Reset SPCR = 0
DDR_SPI |= (1<<MOSI)|(1<<SCK)|(1<<SS);// MOSI,SCK,SS - OUTPUT , MISO - INPUT
SPCR |= (1<<SPE)|(1<<MSTR)|(1<<SPR0); // Enable spi , Set master , div/16
pinMode(red,OUTPUT); // led output at pin 2
pinMode(6,INPUT_PULLUP); // internal res input at pin6
pinMode(7,INPUT_PULLUP); // internal res input at pin7
sbi(PORT_SPI,SS); // disable slave
}
uint8_t SPI_MasterTransmit(uint8_t cData)
{
SPDR = cData; // Start transmission
delay(50);
while(bit_is_clear(SPSR,SPIF)); //Wait for transmission complete
return SPDR;
}
void loop()
{
if(bit_is_clear(PIND,6)) // if i push button at pin 6
{
while(bit_is_clear(PIND,6)); // if i still push button at pin 6
cbi(PORTB,SS); // enable slave
Data1 = SPI_MasterTransmit(1); // send value 1 to slave
Serial.print(Data1); // debug
delay(50);
if(Data1 == 2) //if slave response value = 2
digitalWrite(red,LOW); //turnOFF led at pin 2
sbi(PORT_SPI,SS); // disable slave
}
else if(bit_is_clear(PIND,7)) // if i push button at pin 7
{
while(bit_is_clear(PIND,7)); // if i still push button at pin 7
cbi(PORT_SPI,SS); // disable slave
Data2 = SPI_MasterTransmit(3); // send value 3 to slave
Serial.print(Data2); // debug
delay(50);
if(Data2==4) //if slave response value = 4
digitalWrite(red,HIGH); //turnON led at pin 2
sbi(PORT_SPI,SS); // disable slave
}
}
Arduino Nano (slave) code:
#define MISO 4
#define yellow 2
#define cbi(port, bits) (port) &= ~(1 << (bits))
#define sbi(port, bits) (port) |= (1 << (bits))
volatile uint8_t Data;
void setup()
{
SPCR = 0; // reset SPCR = 0
DDRB |= (1<<MISO); // MISO - OUTPUT , SCK,MOSI,SS - INPUT
SPCR |= (1<<SPE)|(1<<SPIE); // enable spi , spi_interrupt
pinMode(yellow ,OUTPUT); // Led output at pin2
}
void SPI_Response(uint8_t cData)
{
SPDR = cData; //Start transmission
while(bit_is_clear(SPSR,SPIF)); //Wait for transmission complete
}
void loop()
{
}
ISR(SPI_STC_vect) // Vector interrupt spi
{
Data = SPDR; // volatile Data = data receive
if(Data == 1)
{
digitalWrite(yellow ,HIGH); // i turnOn led if i receive data = 5
SPI_Response(2); // and response to master a value = 7
delay(10);
}
else if(Data == 3)
{
digitalWrite(yellow,LOW); // i turnOFF led if i receive data = 6
SPI_Response(4); //and response to master a value = 8
delay(10);
}
}
You know the four wire SPI is full duplex, right? The master and the slave are sending the data simultaneously.
The common way how to do what you want is sending control byte and then dummy byte (or bytes) to receive the data.

Variadic functions not working on arduino

I'm trying to write my own basic libraries to program the Arduino in pure C++. I've tried using a variadic function to implement something similar to Linux's ioctl() to control the SPI module but it just won't work and I have no idea why. I don't pin 13 (Arduino SCK) light up as expected during SPI transactions indicating that SPI is not operating. All the other functions in my library work properly.
The following is my SPI library:
/*
spi.h: SPI driver for Atmega328p
*/
#ifndef _SPI_H
#define _SPI_H
#include <avr/io.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdarg.h>
#include <inttypes.h>
// SPI bus pin mapping ///////////////////////////////////
#define PORT_SPI PORTB // Port register containing SPI pins
#define DDR_SPI DDRB // Data direction register containing SPI pins
#define DDR_SCK DDB5 // Data direction bit of SPI SCK pin
#define DDR_MISO DDB4 // Data direction bit of SPI MISO pin
#define DDR_MOSI DDB3 // Data direction bit of SPI MOSI pin
#define DDR_HWCS DDB2 // Data direction bit of SPI hardware chip select pin
#define PIN_SCK PB5 // Port register bit of SPI SCK pin
#define PIN_MISO PB4 // Port register bit of SPI MISO pin
#define PIN_MOSI PB3 // Port register bit of SPI MOSI pin
#define PIN_HWCS PB2 // Port register bit of SPI hardware chip select pin
// SPI ioctl commands ////////////////////////////////////
#define SPIIOCCONF 0 // Configure SPI command
#define SPIIOCDECONF 1 // Deconfigure SPI command
#define SPIIOCTRANSMIT 2 // SPI byte exchange command
// Clock frequency settings //////////////////////////////
#define SCK_DIV2 2 // Divide source pulse by 2
#define SCK_DIV4 4 // Divide source pulse by 4
#define SCK_DIV8 8 // Divide source pulse by 8
#define SCK_DIV16 16 // Divide source pulse by 16
#define SCK_DIV32 32 // Divide source pulse by 32
#define SCK_DIV64 64 // Divide source pulse by 64
#define SCK_DIV128 128 // Divide source pulse by 128
// SPI modes /////////////////////////////////////////////
#define SPI_MODE0 0
#define SPI_MODE1 1
#define SPI_MODE2 2
#define SPI_MODE3 3
// SPI transaction data orders ///////////////////////////
#define LSBFIRST 0
#define MSBFIRST 1
// The SPI module ////////////////////////////////////////
class spiModule {
private:
bool configured; // Indicates whether SPI is operating with a valid configuration
uint8_t ddrOld, portOld; // Value of DDR_SPI and PORT_SPI just before an SPI configuration was called for
// ( These variables are used to restore the state of the
// SPI pins when SPI is deconfigured )
/* ioctls used to operate the SPI module */
void spiiocconf(int, int, int); // Configure SPI with a valid clock frequency, data order and SPI mode
void spiiocdeconf(void); // Deconfigure SPI and restore SPI pins to their original states
void spiioctransmit(uint8_t, uint8_t *); // Exchange a byte of data over SPI
/* ioctl handlers */
/* These routines check the validity of the arguments and call the ioctls (above) only if all arguments make sense */
/* I've tested these functions by making them public and found that they work perfectly */
int conf(int, int, int); // call spiiocconf() if arguments are valid and SPI is configured
int deconf(void); // call spiiocdeconf() if all arguments are valid and SPI is configured
int transmit(uint8_t, uint8_t *); // call spiioctransmit() if all arguments are valid and SPI is configured
public:
spiModule(void); // Initialize this class
int ioctl(int action, ... ); // Core ioctl handler (supposed to work like the Linux ioctl() system call). But this one just won't work.
};
spiModule spi; // Object of class spiModule for using SPI
// Constructor ///////////////////////////////////////////
spiModule::spiModule(void) {
configured = false;
}
// Private routines //////////////////////////////////////
/* Ioctls */
void spiModule::spiiocconf(int clkDiv, int dataOrder, int mode) {
// Store the values of DDR_SPI and PORT_SPI so they may be recovered when SPI is deconfigured
ddrOld = DDR_SPI;
portOld = PORT_SPI;
// Configure SCK, MOSI and HWCS as output pins and MISO as an input pin
DDR_SPI |= (_BV(DDR_HWCS) | _BV(DDR_SCK) | _BV(DDR_MOSI));
DDR_SPI &= ~_BV(DDR_MISO);
// Power up the SPI module
PRR &= ~_BV(PRSPI);
// Enable SPI and configure it as master
SPCR = 0x00;
SPCR |= (_BV(SPE) | _BV(MSTR));
// Set data order
switch(dataOrder)
{
case LSBFIRST:
SPCR |= _BV(DORD);
break;
case MSBFIRST:
SPCR &= ~_BV(DORD);
break;
}
// Set SPI mode
switch(mode)
{
case SPI_MODE0:
SPCR &= ~(_BV(CPOL) | _BV(CPHA));
break;
case SPI_MODE1:
SPCR |= _BV(CPHA);
SPCR &= ~_BV(CPOL);
break;
case SPI_MODE2:
SPCR &= ~_BV(CPHA);
SPCR |= _BV(CPOL);
break;
case SPI_MODE3:
SPCR |= (_BV(CPOL) | _BV(CPHA));
break;
}
// Set SPI clock frequency
switch(clkDiv)
{
case SCK_DIV2:
SPCR &= ~(_BV(SPR0) | _BV(SPR1));
SPSR |= _BV(SPI2X);
break;
case SCK_DIV4:
SPCR &= ~(_BV(SPR0) | _BV(SPR1));
SPSR &= ~_BV(SPI2X);
break;
case SCK_DIV8:
SPCR |= _BV(SPR0);
SPCR &= ~_BV(SPR1);
SPSR |= _BV(SPI2X);
break;
case SCK_DIV16:
SPCR |= _BV(SPR0);
SPCR &= ~_BV(SPR1);
SPSR &= ~_BV(SPI2X);
break;
case SCK_DIV32:
SPCR &= ~_BV(SPR0);
SPCR |= _BV(SPR1);
SPSR |= _BV(SPI2X);
break;
case SCK_DIV64:
SPCR |= _BV(SPR0);
SPCR |= _BV(SPR1);
SPSR |= _BV(SPI2X);
break;
case SCK_DIV128:
SPCR |= _BV(SPR0);
SPCR |= _BV(SPR1);
SPSR &= ~_BV(SPI2X);
break;
}
// SPI is now configured
configured = true;
return;
}
void spiModule::spiiocdeconf(void) {
// Clear SPI configuration, power down the SPI module and restore the values of DDR_SPI and PORT_SPI
SPCR = 0x00;
PRR |= _BV(PRSPI);
DDR_SPI = ddrOld;
PORT_SPI = portOld;
// SPI is no longer configured
configured = false;
return;
}
void spiModule::spiioctransmit(uint8_t txbyte, uint8_t * rxbyte) {
// Write TX byte to data register
SPDR = txbyte;
while(!(SPSR & _BV(SPIF)))
{
/* wait for data transmission to complete */
}
SPSR &= ~_BV(SPIF);
// Return RX byte by storing it at the specified location
if(rxbyte != NULL)
{
*rxbyte = SPDR;
}
return;
}
/* Ioctl handlers (verify that all arguments are appropriate and only then proceed with the ioctl) */
int spiModule::conf(int clkDiv, int dataOrder, int mode) {
// Return with error of SPI is not configured
if(!configured)
{
return -1;
}
// Verify validity of clkDiv (clock pulse division factor)
switch(clkDiv)
{
case SCK_DIV2:
break;
case SCK_DIV4:
break;
case SCK_DIV8:
break;
case SCK_DIV16:
break;
case SCK_DIV32:
break;
case SCK_DIV64:
break;
case SCK_DIV128:
break;
default:
return -1;
}
// Verify validity of dataOrder (order of byte transfer)
switch(dataOrder)
{
case LSBFIRST:
break;
case MSBFIRST:
break;
default:
return -1;
}
// Check validity of mode (SPI mode)
switch(mode)
{
case SPI_MODE0:
break;
case SPI_MODE1:
break;
case SPI_MODE2:
break;
case SPI_MODE3:
break;
default:
return -1;
}
// If all goes well, execute the ioctl
spiiocconf(clkDiv, dataOrder, mode);
return 0;
}
int spiModule::deconf(void) {
// If SPI is configured, deconfigure it
if(!configured)
{
return -1;
}
spiiocdeconf();
return 0;
}
int spiModule::transmit(uint8_t tx, uint8_t * rx) {
// If SPI is configured, make a byte exchange
if(!configured)
{
return -1;
}
spiioctransmit(tx, rx);
return 0;
}
// Public routines ///////////////////////////////////////
int spiModule::ioctl(int action, ... ) {
// This routine checks the value of action and executes the respective ioctl
// It returns with error if the value of action is not valid
va_list ap;
int clkDiv, dataOrder, mode;
uint8_t txbyte;
uint8_t * rxbyte;
int retVal;
switch(action)
{
case SPIIOCCONF:
va_start(ap, action);
clkDiv = va_arg(ap, int);
dataOrder = va_arg(ap, int);
mode = va_arg(ap, int);
va_end(ap);
retVal = conf(clkDiv, dataOrder, mode);
return retVal;
case SPIIOCDECONF:
retVal = deconf();
return retVal;
case SPIIOCTRANSMIT:
va_start(ap, action);
txbyte = va_arg(ap, uint8_t);
rxbyte = va_arg(ap, uint8_t*);
va_end(ap);
retVal = transmit(txbyte, rxbyte);
return retVal;
default:
return -1;
}
}
#endif
I'm compiling and uploading my code to the Arduino using the following commands (spiTest.cpp is a code that I used to test this library)
COMPILER=~/Softwares/arduino-1.6.8/hardware/tools/avr/bin/avr-g++
HEXGENERATOR=~/Softwares/arduino-1.6.8/hardware/tools/avr/bin/avr-objcopy
UPLOADER=~/Softwares/arduino-1.6.8/hardware/tools/avr/bin/avrdude
AVRDUDE_CFG=~/Softwares/arduino-1.6.8/hardware/tools/avr/etc/avrdude.conf
$COMPILER -c -g -w -D F_CPU=16000000UL -mmcu=atmega328p -std=gnu++11 -o spiTest.o spiTest.cpp
$COMPILER -mmcu=atmega328p spiTest.o -o spiTest
$HEXGENERATOR -O ihex -R .eeprom spiTest spiTest.hex
$UPLOADER -C $AVRDUDE_CFG -v -p atmega328p -c arduino -P /dev/ttyACM0 -b 115200 -D -U flash:w:spiTest.hex:i
I've used variadic functions to implement ioctl() before and it worked when I used the Arduino IDE to compile and upload my program. I don't understand what's preventing variadic functions from working properly in this code.
You are in the C++, you can do it in better. For example something like:
class SPIIOCONF_t {} SPIIOCONF;
class SPIIOCDECONF_t {} SPIIOCDECONF;
class SPIIOCTRANSMIT_t {} SPIIOCTRANSMIT;
int ioctl(SPIIOCONF_t, int clkDiv, int dataOrder, int mode) {
return conf(clkDiv, dataOrder, mode);
}
int ioctl(SPIIOCDECONF_t) {
return deconf();
}
int ioctl(SPIIOCTRANSMIT_t, uint8_t txbyte, uint8_t rxbyte) {
return transmit(txbyte, rxbyte);
}
void setup() {
Serial.begin(115200);
Serial.println(ioctl(SPIIOCONF, 10, 1, 1));
Serial.println(ioctl(SPIIOCDECONF));
uint8_t rx;
Serial.println(ioctl(SPIIOCTRANSMIT, 0xFF, &rx));
}
or similarly without defining dummy class instance, but you have to create one in the call:
class SPIIOCONF {};
class SPIIOCDECONF {};
class SPIIOCTRANSMIT {};
int ioctl(SPIIOCONF, int clkDiv, int dataOrder, int mode) {
return conf(clkDiv, dataOrder, mode);
}
int ioctl(SPIIOCDECONF) {
return deconf();
}
int ioctl(SPIIOCTRANSMIT, uint8_t txbyte, uint8_t rxbyte) {
return transmit(txbyte, rxbyte);
}
void setup() {
ioctl(SPIIOCONF{}, 10, 1, 1);
uint8_t rx;
Serial.println(ioctl(SPIIOCTRANSMIT{}, 0xFF, &rx));
ioctl(SPIIOCDECONF{});
}

Controlling MSP430 PWM with a Laptop

I have written a code which takes two digit number from laptop and changes the PWM dutycycle to that number. It is part of a bigger requirement where I need to control motor speed over UART.
#include "io430g2553.h"
#include <stdint.h>
void PWM(uint8_t duty_cycle);
void PWM_Config();
int main( void )
{
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
WDTCTL = WDTPW + WDTHOLD;
BCSCTL1 = CALBC1_1MHZ; // Run at 1 MHz
DCOCTL = CALDCO_1MHZ; // Run at 1 MHz
PWM_Config();
PWM(5);
__delay_cycles(5000000);
PWM(15);
__delay_cycles(5000000);
PWM(25);
__delay_cycles(5000000);
PWM(50);
__delay_cycles(5000000);
PWM(25);
__delay_cycles(5000000);
PWM(15);
__delay_cycles(5000000);
PWM(5);
while(1)
{}
}
void PWM_Config()
{
P1OUT &= 0x00; // Clearing P1OUT
P1SEL |= BIT6 ;
P1SEL2 &= ~BIT6 ;
P1DIR |= BIT6; // Configuring P1.6 as Output
}
void PWM(uint8_t duty_cycle)
{
TA0CTL =0;
TA0CTL |= TACLR;
TA0CCR1 |= (duty_cycle*100);
TA0CCR0 |= 10000;
TA0CTL |= TASSEL_2 + MC_1 + ID_0;// Register TA0CTL -> SMCLK/8, Up mode
TA0CCTL1 |= OUTMOD_7 ;//Set/Reset Mode
TA0CCTL0 &= ~CCIE; // Interrupt Disabled}
The problem with the void PWM(uint8_t duty_cycle) function is that first time it generates the correct PWM at P1.6, next if it is given a value it changes PWM to that DC, but I can not go back to lower DC.
the fisrt 2 PWM functions in the code changes to correct duty cycle PWM(5),PWM(15) then the rest of PWM values do not produce desired dutycycle.
I am not able to troubleshoot where am I wrong, can any1 help?
Thanks
Seems like a stupid mistake on my part..
TA0CCR1 |= (duty_cycle*100);
instead of
TA0CCR1 = (duty_cycle*100);

Resources