Without using interrupts produce a rising sawtooth waveform - c

Here I need to output a waveform on oscilloscope in C which should in a rising sawtooth waveform.I am not sure if my code is correct. Any help or suggestions?
while(1)
{
for (i = 1; i < 360; i++);
// Check to see if status.TRDY is 1
while(*(base+2) & 0x40 != 1);
// while shift register is not empty
// Make the sawtooth pattern
if (saw == 0x1fff){
saw = 0x1000;
}
else {
saw = saw+1;
}
// transmit sawtooth to the oscilloscope
*(base+1) = saw;
}

This only tidies up the OP's posted code. It does not answer how to program the DAC. OP is using a 16-bit amplitude value but his register addressing suggests 8-bit registers - perhaps two writes are needed.
I suggest you also need function arguments defining the period of the sawtooth wave, and the number of steps. You also need an exit condition. I leave these points to you.
#Chris Stratton also commented that the I/O port should be the correct language type.
#define MINSAW 0x1000
#define MAXSAW 0x1FFF
unsigned *base = (unsigned *)0xD000; // "insert your value"
int main() {
unsigned saw, i;
while(1) {
for (i = 0; i < 360; i++) {
// ratio the waveform amplitude
saw = MINSAW + i * (MAXSAW - MINSAW) / 359;
// Check to see if status.TRDY is 1
while((*(base+2) & 0x40) != 0x40);
// transmit sawtooth to the oscilloscope
*(base+1) = saw;
}
}
return 1;
}

Related

XMC4400 and MAX44009 sensor light (I2C)

I'm having trouble trying to connect my light sensor (MAX44009) with I2C. I will explain what I've done and I hope someone can help me.
I am connecting this connection card on HMI port of my XMC4400 with 80 ports.
I've connected the sensor according to this table.
SCA - pin37
SCL - pin38
GND - pin 80
3.3 - pin 3.3V of XMC4400
Then I've tried to adapt the I2C Master example (available on DAVE tutorials) for my light sensor. I've created an I2C master app with the following settings:
My main.c is this:
Code:
#include <DAVE.h>
#define IO_EXPANDER_ADDRESS (0x4A)
uint8_t tx_buffer[4] = {0x00,0x01,0x02,0x03};
volatile uint8_t tx_completion_0 = 0;
volatile uint8_t rx_completion_0 = 0;
/* Transmit callback handling */
void tx_callback_0(void)
{
tx_completion_0 = 1;
}
/* Receive callback handling */
void rx_callback_0(void)
{
rx_completion_0 = 1;
}
/* Delay */
void delay(uint32_t counter)
{
volatile uint32_t cnt = counter;
while(--cnt);
}
/*
* For this demo the HMI satellite board for the XMC45 CPU board is required.
* It communicates with the IO expander (U360: PCA9502) found in the mentioned satellite board.
* The demo implements a binary counter using the LEDs attached to the IO expander.
*
*/
int main(void)
{
DAVE_Init();
uint8_t received_data;
uint8_t counter = 0;
/* Write data to reset the LEDs through the IO EXPANDER: DIR and 0xFF */
I2C_MASTER_Transmit(&I2C_MASTER_0,true,IO_EXPANDER_ADDRESS,&tx_buffer[1],2,false);
while(tx_completion_0 == 0);
tx_completion_0 = 0;
while(counter < 255)
{
tx_buffer[3] = ~counter;
counter++;
/* Write data to set the STATE of the IO EXPANDER */
I2C_MASTER_Transmit(&I2C_MASTER_0,true,IO_EXPANDER_ADDRESS,&tx_buffer[3],2,false);
while(tx_completion_0 == 0){
tx_callback_0();
}
tx_completion_0 = 0;
/* Receive the data from the IO EXPANDER */
I2C_MASTER_Receive(&I2C_MASTER_0,true,IO_EXPANDER_ADDRESS,&received_data,2,true,true);
printf("%d", received_data);
while(rx_completion_0 == 0){
rx_callback_0();
}
rx_completion_0 = 0;
/* Check if the received data is correct*/
if(tx_buffer[3] != received_data)
{
// while(1);
}
/* Delay to make visible the change */
delay(0xfffff);
}
while(1);
return 0;
}
I think my callback functions are not working, since it stops every time I execute one I2C function. on this case is on line 108. Plus, sometimes it gives me an error/warning:
No source available on 0x00.
import smbus
import time
# Get I2C bus
bus = smbus.SMBus(1)
# MAX44009 address, 0x4A(74)
# Select configuration register, 0x02(02)
# 0x40(64) Continuous mode, Integration time = 800 ms
bus.write_byte_data(0x4A, 0x02, 0x40)
time.sleep(0.5)
# MAX44009 address, 0x4A(74)
# Read data back from 0x03(03), 2 bytes
# luminance MSB, luminance LSB
data = bus.read_i2c_block_data(0x4A, 0x03, 2)
# Convert the data to lux
exponent = (data[0] & 0xF0) >> 4
mantissa = ((data[0] & 0x0F) << 4) | (data[1] & 0x0F)
luminance = ((2 ** exponent) * mantissa) * 0.045
# Output data to screen
print "Ambient Light luminance : %.2f lux" %luminance
I have this Python code that works fine on my sensor light when I'm using raspberry pi, I've tried to do the same thing on XMC but without success. I hope you can help me.
First of all I would recommend to build a if statement arround your code
like
DAVE_STATUS_t init_status;
init_status = DAVE_Init();
if(init_status == DAVE_STATUS_SUCCESS)
{
... code
}
With this you can check if the DAVE APP is initialized correct. If it is the case you can look further into the callback issue. If not it's a problem with the configuration.
You can find further code exampels by rightlciking on the I2C Master field in teh APP Dependency window -> APP Help. There are examples for the methods provided by the APP.

Unwanted Jump to interrupt MPLAB X IDE v.3.30

I am new to programming on micro controllers and I am trying to write a timer program for the PICLF1571. Every time it wakes from sleep, it's supposed to write to the flash memory. When I debug it with the simulation, it's able to write once, but once it loops the program gets stuck in the interrupt routine. If I comment out the Interrupt routine, the simulation jumps to another place or goes to 0x00.
The only time I see the program get stuck is when the function flash_write is used.
What could be some causes for interrupts to occur if no flags are triggered?
pin setup
void init(void){
ANSELA = 0x0; //|-> Pin setup
TRISA = 0x0;
TRISAbits.TRISA5 = 1;
PORTA = 0x0;
LATA = 0x0;
INTCONbits.GIE = 1; //|-> Interrupt setup
INTCONbits.IOCIE = 1;
IOCAP = 0x0;
IOCAPbits.IOCAP5 = 0;
INTCONbits.IOCIF = 0;
IOCAF = 0x0;
IOCAFbits.IOCAF5 = 0;
WDTCONbits.SWDTEN = 1; //|-> Watchdog Timer setup
WDTCONbits.WDTPS = 0b00001;// reconfigure for correct speed
//currently 0b10001
}
main
//#include <stdio.h>
#include <xc.h>
#include "init.h"
#include "Interrupt.h"
#include "flash.h"
int main(void){
init();
unsigned short ad = 1;
unsigned short f = 0x3FFF;
unsigned short a = 0x0000;
unsigned short ret = 0x0000;
flash_erase(0x0000);
while(1) {
asm("sleep");
flash_write(a,f);
//flash_erase(a);
//flash_read1(a,&ret);
}
return 1;
}
flash_write function. Instructions based on flowchart in datasheet
void flash_write(unsigned short addr, unsigned short data){
INTCONbits.GIE = 0; //||]->start write
PMCON1bits.CFGS = 0;//||]
PMADRH = (unsigned char)((addr >> 8) & 0xFF);
PMADRL = (unsigned char)(addr & 0xFF);
PMCON1bits.FREE = 0;//||]->enable write
PMCON1bits.LWLO = 1;//||]
PMCON1bits.WREN = 1;//||]
PMDATH = (unsigned char)((data >> 8) & 0xFF);
PMDATL = (unsigned char)(data & 0xFF);
PMCON1bits.LWLO = 0;
PMCON2 = 0x55; //||]->unlock sequence
PMCON2 = 0xAA; //||]
PMCON1bits.WR = 1; //||]
NOP(); //||]
NOP(); //||]
PMCON1bits.WREN = 0;//]->end write
INTCONbits.GIE = 1;
asm("RETURN");
}
interrupt routine
#include <xc.h>
void interrupt button(void){
if (INTCONbits.IOCIE == 1 && IOCAFbits.IOCAF5 == 1 ){
int time = 0;
while (PORTAbits.RA5 == 1){//RA5 in sim never changes. always 0
time++;
if (time >= 20000 && PORTAbits.RA5 == 1){
LATA = 0x0;
asm("NOP");
break;
}
if ( time < 20000 && PORTAbits.RA5 == 0){
asm("NOP");
break;
}
}
IOCAF = 0x0;
INTCONbits.IOCIF = 0;
asm("RETFIE");
}
}
0000h is the reset vector address; once written, subsequent resets will jump to 0x3fff, which is not a valid address on a device with only 0x3ff words of flash. Note that since 0x3fff is the erased state of flash memory, the write in this case actually has no effect that is not already caused by the erase alone.
Also understand that, the PIC12 flash memory is word-write/row-erase, and a row is 16 words. So the erase operation will wipe out the entire vector table and the start of the program area too. You are essentially modifying the code, but not in a manner than makes any sense (if it makes sense at all).
You should reserve an area of flash using appropriate linker directives and well away from the vector table (probably the entire last row at 0x3f0, to prevent the linker locating code in the space you want to write at run time.
Another issue is that the flash cell endurance on PIC12F1571 is only 10000 erase/write cycles - are you sure you want to write to the same address every time the device boots? If you "stripe" the reserved row and write to each of the 16 words in turn before erasing the row and restarting, you will increase endurance to 160000 cycles. Add more rows to get greater endurance. Since erased flash has a value 0x3fff (14 bit words), to find the "current value" you need to scan the reserved row(s) for the last value that is not 0x3fff (0x3fff is implicitly therefore not a valid actual value).

UART receive string

I am using an MSP430 and writing code in C. I am receiving characters (working) via UART and placing them into an array rxDataArray. Since I am using an MSP430G2211, I have limited memory. The maximum array size is 50 and any more it won't build/load and says out of space.
My MSP430 is communicating to a ESP8266 module (wifi) where I am using "AT" commands. I am receive an echo of my AT command, followed by a response (ex. AT+RST responds with AT+RST...ok). I am confused using C, how I can make a string with just the "ok" response and check if it worked correctly. I have the data in the array, just not sure how to pick certain elements of the array, make a string, and compare that to "ok" response. I am used to using CString in C++ and am confused how to do this in C.
/--------------------------------------------------------------------
// Timer_A UART - Receive Interrupt Handler
//-------------------------------------------------------------------
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = TIMERA1_VECTOR
__interrupt void Timer_A1_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(TIMERA1_VECTOR))) Timer_A1_ISR (void)
#else
#error Compiler not supported!
#endif
{
static unsigned char rxBitCnt = 8;
static unsigned char rxData = 0;
switch (__even_in_range(TAIV, TAIV_TAIFG)) { // Use calculated branching
case TAIV_TACCR1: // TACCR1 CCIFG - UART RX
TACCR1 += UART_TBIT; // Add Offset to CCRx
if (TACCTL1 & CAP) { // Capture mode = start bit edge
TACCTL1 &= ~CAP; // Switch capture to compare mode
TACCR1 += UART_TBIT_DIV_2; // Point CCRx to middle of D0
}
else {
rxData >>= 1;
if (TACCTL1 & SCCI) { // Get bit waiting in receive latch
rxData |= 0x80;
}
rxBitCnt--;
if (rxBitCnt == 0) { // All bits RXed?
rxBuffer = rxData; // Store in global variable
if (rxDataCnt < 50)
{
rxDataArray[rxDataCnt] = rxBuffer;
rxDataCnt++;
}
else
{
int i = 0;
for (i; i<50-1; i++)
{
rxDataArray[i] = rxDataArray[i+1];
}
rxDataArray[50-1] = rxBuffer;
}
rxBitCnt = 8; // Re-load bit counter
TACCTL1 |= CAP; // Switch compare to capture mode
__bic_SR_register_on_exit(LPM0_bits); // Clear LPM0 bits from 0(SR)
}
}
break;
}
}
//-----------------------------------------------------------------------
You can turn OFF echo by sending ATE0 command.
Also to find the intended string response please follow below steps:
Enable UART Transmit and Receive Interrupt.
After completing your command transmission you will start receiving data in UART ISR.
In the receive interrupt start a timer of say 1 second(You need to consider baud-rate for exact calculation).
Make track of number of received bytes in UART ISR.
Now after timer expires add null to end of last received byte in buffer.
Now,You can use string manipulation functions of C to find the intended response.

Reading serial port with initial data results in lots of zeros

I'm testing a serial implementation and when I open a serial port (I have an Arduino spitting out lines of compass data.) sometimes I get a bunch of zeros initially. I had thought this was leftover data from before, but it does not seem to be (flushing IO doesn't seem to help)
This is a programming language serial implementation written in C and I'm testing this on Linux, but had similar results with Windows.
The strace output shows this on the first read:
read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 34815) = 1544
write(1, "== ", 3== ) = 3
write(1, "#{\n00000000000000000000000000000"..., 503#{
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000583A20353333202020593A20313020
20205A3A2033313920202058733A2033393520202059733A203136312020205A
733A20323933202020483A20302E3436202020413A...) = 503
I have tried adding the following line to clear this data just before the port is closed, after it is opened, and after the attributes it has set:
tcflush(ttyfd, TCIOFLUSH);
but it doesn't seem to help with this issue. Any thoughts about how to clean this up?
The code is from a large project and I have collected some of the relevant parts below, the variables are declared even if not shown but should be clear enough
Opening the port:
ttyfd = open(&devpath[0], O_RDWR | O_NOCTTY | O_NONBLOCK); // ttyUSB0 in this case
Changing settings:
if (speeds[n] == 0) speed = B115200; // invalid, use default
cfsetospeed (&attr, speed);
cfsetispeed (&attr, speed);
// C-flags - control modes:
attr.c_cflag |= CREAD | CS8 | CLOCAL;
// L-flags - local modes:
attr.c_lflag = 0; // raw, not ICANON
// I-flags - input modes:
attr.c_iflag |= IGNPAR;
// O-flags - output modes:
attr.c_oflag = 0;
// Control characters:
// device is non-blocking (polled for changes):
attr.c_cc[VMIN] = 0;
attr.c_cc[VTIME] = 0;
// Make sure OS queues are empty:
tcflush(ttyfd, TCIOFLUSH);
// Set new attributes:
if (tcsetattr(ttyfd, TCSANOW, &attr)) return 2;
This is the Arduino code sending data from an OSEPP Compass module
// OSEPP Compass Sensor Example Sketch
// by OSEPP <http://www.osepp.com>
// Modifications by Chris W. to accommodate declination, scaling and origin adjustment 2013-02-13
// This sketch demonstrates interactions with the Compass Sensor
#include <Wire.h>
const uint8_t sensorAddr = 0x1E; // Sensor address (non-configurable)
const float xOffset = 103.0; // Offset required to adjust x coordinate to zero origin
const float yOffset = -165.0; // Offset required to adjust y coordinate to zero origin
const float declination = 70.1; // Enter magnetic declination mrads here (local to your geo area)
// One-time setup
void setup()
{
// Start the serial port for output
Serial.begin(115200);
// Join the I2C bus as master
Wire.begin();
// Configure the compass to default values (see datasheet for details)
WriteByte(sensorAddr, 0x0, 0x70);
WriteByte(sensorAddr, 0x1, 0x20); // +1.3Ga
// Set compass to continuous-measurement mode (default is single shot)
WriteByte(sensorAddr, 0x2, 0x0);
}
// Main program loop
void loop()
{
uint8_t x_msb; // X-axis most significant byte
uint8_t x_lsb; // X-axis least significant byte
uint8_t y_msb; // Y-axis most significant byte
uint8_t y_lsb; // Y-axis least significant byte
uint8_t z_msb; // Z-axis most significant byte
uint8_t z_lsb; // Z-axis least significant byte
int x;
int y;
int z;
// Get the value from the sensor
if ((ReadByte(sensorAddr, 0x3, &x_msb) == 0) &&
(ReadByte(sensorAddr, 0x4, &x_lsb) == 0) &&
(ReadByte(sensorAddr, 0x5, &z_msb) == 0) &&
(ReadByte(sensorAddr, 0x6, &z_lsb) == 0) &&
(ReadByte(sensorAddr, 0x7, &y_msb) == 0) &&
(ReadByte(sensorAddr, 0x8, &y_lsb) == 0))
{
x = x_msb << 8 | x_lsb;
y = y_msb << 8 | y_lsb;
z = z_msb << 8 | z_lsb;
int xs;
int ys;
int zs;
float gScale = .92; // Scale factor for +1.3Ga setting
float adjx = x - xOffset;
float adjy = y - yOffset;
xs = adjx * gScale;
ys = adjy * gScale;
zs = z * gScale;
float heading = atan2(ys, xs);
heading += declination / 1000; // Declination for geo area
if (heading < 0);
heading += 2*PI;
if (heading > 2*PI)
heading -= 2*PI;
float angle = heading * 180/M_PI;
Serial.print("X: ");
Serial.print(x);
Serial.print(" Y: ");
Serial.print(y);
Serial.print(" Z: ");
Serial.print(z);
Serial.print(" Xs: ");
Serial.print(xs);
Serial.print(" Ys: ");
Serial.print(ys);
Serial.print(" Zs: ");
Serial.print(zs);
Serial.print(" H: ");
Serial.print(heading);
Serial.print(" A: ");
Serial.println(angle);
}
else
{
Serial.println("Failed to read from sensor");
}
// Run again in 1 s (1000 ms)
delay(500);
}
// Read a byte on the i2c interface
int ReadByte(uint8_t addr, uint8_t reg, uint8_t *data)
{
// Do an i2c write to set the register that we want to read from
Wire.beginTransmission(addr);
Wire.write(reg);
Wire.endTransmission();
// Read a byte from the device
Wire.requestFrom(addr, (uint8_t)1);
if (Wire.available())
{
*data = Wire.read();
}
else
{
// Read nothing back
return -1;
}
return 0;
}
// Write a byte on the i2c interface
void WriteByte(uint8_t addr, uint8_t reg, byte data)
{
// Begin the write sequence
Wire.beginTransmission(addr);
// First byte is to set the register pointer
Wire.write(reg);
// Write the data byte
Wire.write(data);
// End the write sequence; bytes are actually transmitted now
Wire.endTransmission();
}
I'll try switch the order of the delay and the serial writing in the arduino code as it may resolve this issue, but the code will remain ineffective for a similar future scenario.
Had a look through the IC's datasheet.
See page 14: Link
Continuous-Measurement Mode. In continuous-measurement mode, the device continuously performs measurements and places the result in the data register. RDY goes high when new data is placed in all three registers. After a power-on or a write to the mode or configuration register, the first measurement set is available from all three data output registers after a period of 2/f_DO and subsequent measurements are available at a frequency of f_DO, where f_DO is the frequency of data output
According to Arduino docs, the Wire library runs at 100KHz. 2/100KHz == 20uS. Assuming your Arduino runs at 16MHz (1 cycle == 62.5ns), you probably aren't waiting long enough to read the registers.
To make your code more robust, I recommend checking the status register's RDY bit before performing any reads. The data is likely correct, but you have to account for the startup time taken by the IC.
If you do this, and find the same issue still occurring, then at least you'll have further isolated the issue.
Alternatively: you can put the 500ms delay at the bottom of your main loop at the top if you just want a quick hack.

Using C with the TI EZ430-RF2500 dev chips

So what I am trying to do is receive a packet and print the payload to the serial port. Listening at the port is a python script that reassembles the payload and does some things with it.
Here is the code:
#include "mrfi.h"
int main(void)
{
BSP_Init();
MRFI_Init();
//Initialize the serial port
P3SEL |= 0x30;
UCA0CTL1 = UCSSEL_2;
UCA0BR0 = 0x41;
UCA0BR1 = 0x3;
UCA0MCTL = UCBRS_2;
UCA0CTL1 &= ~UCSWRST;
MRFI_WakeUp();
MRFI_RxOn();
__bis_SR_register(GIE+LPM4_bits);
}
//This is run when a packet is received
void MRFI_RxCompleteISR()
{
uint8_t i;
P1OUT ^= 0x02;
mrfiPacket_t packet;
MRFI_Receive(&packet);
char output[] = {" "};
for (i=9;i<29;i++) {
output[i-9]='a';
if (packet.frame[i]=='\r') {
output[i-9]='\n';
output[i-8]='\r';
}
}
TXString(output, (sizeof output));
}
I send a packet with test data but nothing. Anybody have any insights? Also while just so you know I am learning C while I do this, so any pointers on design would also be awesome.
Thanks.
I don't know why your code isn't working, but here are some design hints as requested.
Since this appears to be a hostless system, main() should most likely return void. I assume that you didn't post all of your code, as in a hostless there should also be an eternal loop in main().
Remove all "magic numbers" from the code and replace them with #defined bitmasks or constants.
Reduce all code inside interrupts to a minimum. The optimal interrupt only sets some flags.
Don't use unspecified width (output[]) for arrays/strings. Embedded system design is about making things deterministic and fixed.
Here is an example of another way to write that loop. As I have no idea what this program is supposed to do, replace the constant names with something that makes sense.
uint8_t output[OUTPUT_N];
memset(output, ' ', SPACES_N);
output[OUTPUT_N - 1] = '\0';
for(i=0; i < SOMETHING; i++)
{
output[i + A_OFFSET] = 'a';
if(packet.frame[i + FRAME_OFFSET] == '\r')
{
output[i + CR_OFFSET] = '\r';
output[i + LF_OFFSET] = '\n';
}
}

Resources