I'm currently trying to interface my Tiva C Series with a Sparkfun Breakout Board, IMU Digital Combo Board - 6 Degrees of Freedom ITG3200/ADXL345 and I'm having trouble with the I2C interface.
currently this is my code:
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "driverlib/i2c.h"
uint8_t SLAVE_ADDRESS = 0x68;
uint32_t first_byte, second_byte, temperature, result;
void i2c_setup(void) {
//Enable the I2C Module
SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C2);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
//Wait at least 5 clock cycles
SysCtlDelay(2);
//Configure SDA and SCL
GPIOPinConfigure(GPIO_PE4_I2C2SCL);
GPIOPinConfigure(GPIO_PE5_I2C2SDA);
//Wait at least 5 clock cycles
SysCtlDelay(2);
//Set PE4 as SCL
GPIOPinTypeI2CSCL(GPIO_PORTE_BASE, GPIO_PIN_4);
//Set PE5 as SDA
GPIOPinTypeI2C(GPIO_PORTE_BASE, GPIO_PIN_5);
//Configure Master,
I2CMasterInitExpClk(I2C2_BASE, SysCtlClockGet(), false);
}
uint32_t i2c_read() {
I2CMasterSlaveAddrSet(I2C2_BASE, SLAVE_ADDRESS, false);
I2CMasterDataPut(I2C2_BASE, 0x1A);
I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_SINGLE_SEND);
while(I2CMasterBusBusy(I2C2_BASE)); //Loop until the bus is no longer busy
I2CMasterSlaveAddrSet(I2C2_BASE, SLAVE_ADDRESS, true );
I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
while(I2CMasterBusBusy(I2C2_BASE)); //Loop until the bus is no longer busy
first_byte = I2CMasterDataGet(I2C2_BASE);
return first_byte;
}
void setup()
{
Serial.begin(9600);
i2c_setup();
}
void loop()
{
int test = i2c_read();
Serial.println(test);
delay(1000);
}
I'm using Energia to test my program, and when I try to read from the specified register, I get the same result, no matter which register I choose, the result is always decimal 229 (this is the Accelerometer's Device Address).
Can somebody point me in the right direction, I've been looking at my code for quite some time and still don't know whats wrong...
Thanks!
I skimmed through your code and everything seems Okay. Clearly something is working right if you get a response. But Like Martin said , figuring the problem without being there is somewhat difficult. Instead of Writing 0x1A can you try using one of the other I2C commands for the accelerametor ? Also if the jumper is connected to VDD your address should be 0x69 (105 decimal) are you sure it's 0x68 ?
I looked up the documentation on sparkfuns website and they provided the following list
of commands.
char WHO_AM_I = 0x00;
char SMPLRT_DIV= 0x15;
char DLPF_FS = 0x16;
char GYRO_XOUT_H = 0x1D;
char GYRO_XOUT_L = 0x1E;
char GYRO_YOUT_H = 0x1F;
char GYRO_YOUT_L = 0x20;
char GYRO_ZOUT_H = 0x21;
char GYRO_ZOUT_L = 0x22;
GL hope everything works out. Been meaning to buy my own to play around with so keep me posted !
Related
I am doing a major embedded project of making a GM counter. As a main microcontroller I am using a PIC32MK1024MCM064. I wont bore you with details, but I need to implement following algorithm:
When MCU turns on, 13 seconds delay has to pass
MCU waits for a button press, which triggers an interrupt
Button interrupt starts 60 seconds timer
During that 60 seconds, MCU input pin counts the impulses (Idle voltage state is high (3.3V) and low voltage state counts as an impulse (50-130 us duration))
After the timer has expired, MCU outputs the impulse number via 16x2 LCD screen
Project has many files included in it, but I have already verified all the peripheral code is written right:
I have already made sure, that my button interrupt and the timer interrupt work absolutely fine (used the oscilloscope, real timer and all the other stuff.)
I also verified that my I2C driver for the LCD screen works great as well.
I made sure I am indeed getting the low state impulses as defined (50-130 us duration.)
#include <xc.h>
#include "configurations_bits.h"
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include "stdio.h"
#include <sys/attribs.h>
#include "delay.h"
#include "inter_integrated_circuit_protocol.h"
#include "liquid_crystal_display.h"
#include "pulse_width_modulation.h"
#include "timer.h"
#include "state_change_interrupts.h"
static int Particle_count = 0; //Variable for counting events
char Value[10]={0}; //Particle value string
int main(void) {
__builtin_disable_interrupts(); //Global interrupt disable
ANSELA = 0x00000000; //Enable PORT A digital inputs
ANSELG = 0x00000000; //Enable PORT G digital inputs
TRISEbits.TRISE12 = 0; //Output gpio of a led
TRISDbits.TRISD8 = 0; //Output gpio of a led
TRISGbits.TRISG9 = 0; //Output GPIO of GM ENABLE
LATGbits.LATG9 = 1; //Enable GM right away
TRISAbits.TRISA1 = 1; //Input for counting particles
TRISCbits.TRISC7 = 1; //Input for control button
Inter_Integrated_Circuit_Setup (); //I2C configuration
Inter_Integrated_Circuit_Enable (); //I2C enable
Liquid_Crystal_Display_initialization(); //LCD configuration
Liquid_Crystal_Display_Set_Cursor(1, 1);
Liquid_Crystal_Display_Write_String("Preparing for");
Liquid_Crystal_Display_Set_Cursor(2, 1);
Liquid_Crystal_Display_Write_String("Measurement");
Pulse_Width_Modulation_Setup(); //PWM setup
Pulse_Width_Modulation_Enable(); //Turn on high voltage generation
for(int i=0; i<13; i++){
delay_ms(1000);} //Waiting until the high voltage rail rises up to 400V (starting GM tube voltage)
Liquid_Crystal_Display_Clear(); //Clearing LCD
Liquid_Crystal_Display_Set_Cursor(1, 1);
Liquid_Crystal_Display_Write_String("Ready for");
Liquid_Crystal_Display_Set_Cursor(2, 1);
Liquid_Crystal_Display_Write_String("Measurement");
State_Change_Interrupts_Setup (); //Button interrupt setup
Timer2_Setup (); //Timer interrupt setup
__builtin_enable_interrupts(); //Global interrupt enable
while (1){
if(T2CONbits.ON){ //Condition, that the timer is on
Liquid_Crystal_Display_Clear(); //Clearing LCD
Liquid_Crystal_Display_Set_Cursor(1, 1);
Liquid_Crystal_Display_Write_String(" Measurement Is ");
Liquid_Crystal_Display_Set_Cursor(2, 1);
Liquid_Crystal_Display_Write_String(" In Progress ");
while(T2CONbits.ON){ //Execute this while cycle until the timer shuts off
if(PORTAbits.RA1==0){
Particle_count = Particle_count+1;
delay_us(100);} //GM tube dead time compensation
}
Liquid_Crystal_Display_Clear(); //Clearing LCD
sprintf(Value,"%05d CPM",Particle_count);
Particle_count=0; //Resetting the CPM value
Liquid_Crystal_Display_Set_Cursor(1, 1);
Liquid_Crystal_Display_Write_String(Value);//Printing radiation level in CPM notation
delay_ms(5000);
Liquid_Crystal_Display_Clear(); //Clearing LCD
}
}
return (EXIT_FAILURE);
}
When I press the button, my LCD outputs "Measurement Is In Progress" for a fraction of a second, then it immediately outputs "00000 CPM" which means it had counted zero impulses (In my application, I know for sure that I must capture at least 5 impulses per minute.) Looks like the while cycle has only one or few iterations (it should last for a minute). So my code problem is not a missing semicolon somewhere, but I feel like the whole architecture is not right. Have you got any observations or suggestions, how could I implement the mentioned algorithm? Want to thank you in advance.
(P.S I am running a 8 MHz internal FRC as the main clock)
I have an Adafruit Sharp Memory display connected via SPI to Arduino Nano Connect RP2040. I don't use Arduino IDE nor libraries. I write the code in C++ like I would write for RP2040 on Pi Pico, so I'm using Pico/RP2040 libraries. I'm building it and then just copying the .uf2 file to Arduino.
I'm trying to control the display but without success and I have no idea what I'm doing wrong. Here is my code, where I'm sending a command which should clear the display but it does not:
#include <stdio.h>
#include <stdlib.h>
#include "pico/stdlib.h"
#include "hardware/spi.h"
#include "hardware/gpio.h"
// ---SPI
// Pins for Arduino
#define SCK_PIN 13 // SCLK / SCK
#define MOSI_PIN 11 // MOSI / COPI
#define SS_PIN 10 // SS / CS
// ---Sharp display
#define WIDTH 144
#define HEIGHT 168
int main() {
stdio_init_all();
printf("START \n");
bool vcom_bool_{false};
spi_init(spi0, 2000000);
spi_set_format( spi0, 8, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST);
gpio_set_function(MOSI_PIN, GPIO_FUNC_SPI);
gpio_set_function(SCK_PIN, GPIO_FUNC_SPI);
gpio_init(SS_PIN);
gpio_set_dir(SS_PIN, GPIO_OUT);
gpio_put(SS_PIN, 0); // this display is low on inactive
while(true)
{
printf("VCOM = %b \n", vcom_bool_);
gpio_put(SS_PIN, 1);
// Clear the display
uint8_t buf[2];
if(vcom_bool_)
{
buf[0] = 0b01100000;
vcom_bool_ = false;
}
else
{
buf[0] = 0b00100000;
vcom_bool_ = true;
}
buf[1] = 0b00000000;
spi_write_blocking(spi0, buf, 2);
gpio_put(SS_PIN, 0);
sleep_ms(10);
sleep_ms(500);
}
}
Display and wiring are ok, because when I run example code from Adafruit (it is using Arduino's libraries) it works.
I follow this documentation from Sharp: https://www.sharpsde.com/fileadmin/products/Displays/2016_SDE_App_Note_for_Memory_LCD_programming_V1.3.pdf
I also reviewed the code from Adafruit and the SPI communication seems to be done in the same way.
What am I doing wrong?
Is there some issue with using Pico libraries for Arduino Nano RP2040? I did I2C communication in the same way (Pico/RP2040 libraries, .uf2 copied to Arduino Nano RP2040) and it worked.
I would like to measure a pulse using the pic 18f4550 in capture mode, this pulse is generated by the pic microcontroller itself, for this I use a function which plays the role of the XOR logic gate (you find the function that I've used below). with RC0 and RC2 the inputs and RC6 the signal output. the pulse leaving RC6 enters ccp2 to be measured.
The problem I found is that the ccp2 cannot detect the impulse generated by the microcontroller. I don't know if there are any conditions to connect the pins of the microcontroller or something.
If anyone has an answer or a hint to fix this, I will be grateful!
and if you have any questions feel free to ask .thanks !!
UPDATE: I changed some instructions in the code, now the RC6 output provides a signal. but my LCD does not display anything. the RC6 output is present below.
UPDATE 2: the while(1) in the xor() function blocking the rest of my program, so the program never get out of xor() and my LCD wont display anything. when I don't use the while loop in xor () my RC6 produce anything, the same for the LCD.
I don't know where the problem is, I did everything in my power to find the bug . but the system still not working!!!
I will leave the program as it is, so new readers can understand what I am talking about.
#include <stdio.h>
#include <stdlib.h>
#include "osc_config.h"
#include "LCD_8bit_file.h"
#include <string.h>
unsigned long comtage,capt0,x;
char pulse[20];
char cosinus[20];
float period,dephTempo,deph,phi;
void init (){
IRCF0 =1; /* set internal clock to 8MHz */
IRCF1 =1;
IRCF2 =1;
PIE2bits.CCP2IE=1;
PIR2bits.CCP2IF=0;
CCPR2 =0; /*CCPR1 is capture count Register which is cleared initially*/
T3CONbits.RD16=1;
T3CKPS0=0;
T3CKPS1=0;
TMR3CS=0;
TMR3IF=0;
T3CCP2=0; /*Timer3 is the capture clock source for CCP2*/
}
void xor()
{
while(1)
{
if (PORTCbits.RC0==PORTCbits.RC2)
{
PORTCbits.RC6=0;
}
else if (PORTCbits.RC0!=PORTCbits.RC2)
{
PORTCbits.RC6=1;
}
}
}
void main()
{
TRISCbits.TRISC0=1;
TRISCbits.TRISC2=1;
TRISCbits.TRISC6=0;
xor();
LCD_Init();
while(1)
{
CCP2CON = 0b00000101;
PIR2bits.CCP2IF = 0;
TMR3ON = 0;
TMR3 = 0;
while (!PIR2bits.CCP2IF);
TMR3ON = 1;
CCP2CON = 0b00000100;
PIR2bits.CCP2IF = 0;
while (!PIR2bits.CCP2IF);
comtage = CCPR2;
dephTempo = (((float)comtage /30.518)/65536 );
sprintf(pulse,"%.3f ",dephTempo);
LCD_String_xy(0,0,"the pulse width is : ");
LCD_String_xy(2,9,pulse);
}
}
So I am having a tough time setting up my SPI, and getting it to work with the LSM330 device to read accelerometer data. I'm simply setting up the SPI system, and trying to use that to read the WHO_AM_I_A register to confirm that it is working and all I'm getting back is 0xff rather than 0x40.
Here is my code:
main.c
#include <avr/io.h>
#include "LSM330.h"
#include "spi.h"
#include "CLK.h"
#include "accel.h"
int main(void) {
//set clock
set32MhzClock();
//first set SPI slave selects for accel gyro to false(high)
PORTF.OUTSET = PIN4_bm | PIN3_bm;
//set serial system of SPI
PORTA_OUTCLR = PIN4_bm;
//init SPI
spi_init();
//reset LSM330 accel by sending 0x01 to CTRL_REG4_A
accel_write(0x01, CTRL_REG4_A);
//trying to read from WHO_AM_I_A reg
uint8_t whoAreYou = accel_read(WHO_AM_I_A);
printf(whoAreYou);
}
accel.h
#include "LSM330.h"
#include "spi.h"
void accel_write(uint8_t reg_addr, uint8_t data) {
//make slave select signal LOW
PORTF_OUTCLR = PIN3_bm;
//set sensor_sel
PORTF_OUTSET = PIN2_bm;
//first write reg_addr, w/ RW=0 and MS=0
uint8_t writeResult = spi_write(reg_addr);
//then write data byte
spi_write(data);
return;
}
spi.h
void spi_init(void) {
//set correct pins as outputs and inputs
PORTF.DIRSET = PIN7_bm | PIN5_bm | PIN4_bm | PIN3_bm; //SCK, MOSI, SSG, SSA as outputs
PORTF.DIRCLR = PIN6_bm; //MISO as input
//set up SPI as master
SPIF.CTRL = SPI_ENABLE_bm | SPI_MASTER_bm | SPI_MODE_3_gc | SPI_PRESCALER_DIV16_gc;
//clear spi interrupt flag by reading spsr and spdr
SPIF_STATUS;
SPIF_DATA;
return
}
uint8_t spi_write(uint8_t dataIn) {
//write data
SPIF.DATA = dataIn;
//wait for transmission to complete
while(!(SPIF_STATUS & SPI_IF_bm));
return SPIF.DATA;
}
uint8_t spi_read(vodi) {
return spi_write(0xFF);
}
And that's all I have. Have tried many things, and can't seem to get this thing to work. It seems like SPI is working because it's not getting stuck up in any of the while loops when writing data.
Without going too much into the details, there is definitely something wrong here:
//reset LSM330 accel by sending 0x01 to CTRL_REG4_A
accel_write(0x01, CTRL_REG4_A);
But the declaration of your function is as follows:
void accel_write(uint8_t reg_addr, uint8_t data)
It seems you are setting register 0x01 to value of CTRL_REG4_A.
I need to read values form a distance sensor in volts. The sensor sends the voltages binary values to the MUC (Atmega8) and then the atmega8 communicates to my pc using USART with and RS232 cable. The readings displayed on the PC are weird random characters. I don't understand what am I doing wrong.
Here is my code
//USART communicating with Atmega8
#include <avr/io.h>
#include <inttypes.h>
#include <util/delay.h>
#include <string.h>
//1MHZ Baud 9600
#define F_CPU 1000000
char *Bestbelieve ="t \r\n";
void InitADC()
{
ADMUX=(0<<REFS1)|(1<<REFS1); // For Aref=internal;
ADCSRA=(1<<ADEN)|(0<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); //Prescalar div factor =8
}
uint16_t ReadADC()
{
ADMUX=0x05;
//Start Single conversion
ADCSRA|=(1<<ADSC);
//Wait for conversion to complete
while(!(ADCSRA & (1<<ADIF)));
//Clear ADIF by writing one to it
//Note you may be wondering why we have write one to clear it
//This is standard way of clearing bits in io as said in datasheets.
//The code writes '1' but it result in setting bit to '0' !!!
ADCSRA|=(1<<ADIF);
return(ADC);
}
void Wait()
{
uint8_t i;
for(i=0;i<20;i++)
_delay_loop_2(0);
}
char USARTReadChar()
{
//Wait until a data is available
while(!(UCSRA & (1<<RXC)))
{
//Do nothing
}
//Now USART has got data from host
//and is available is buffer
return UDR;
}
void USARTWriteChar(char* data)
{
//Wait until the transmitter is ready
while(*data)
{ while(!(UCSRA & (1<<UDRE)))
{
//Do nothing
}
//Now write the data to USART buffer
UDR=*data;
data++;
}}
void USARTInit(uint16_t ubrr_value)
{
UBRRL = 12;
UBRRH = 0;
UCSRC=(1<<URSEL)|(3<<UCSZ0);
UCSRB=(1<<RXEN)|(1<<TXEN);
UCSRA=(1<<U2X);
}
int main()
{
uint16_t adc_result;
//Initialize ADC
InitADC();
USARTInit(12); //UBRR = 12
//Loop forever
while(1)
{
adc_result=ReadADC(); // Read Analog value from channel-0
char *result[15];
sprintf(result,"%d",adc_result);
Wait();
USARTWriteChar(adc_result);
/* The code continuously has t outputted and skipped lines.
*/
}
}
You are using sprintf to format your data into result. However, you then use USARTWriteChar on your binary value adc_result.
You need to print out result instead, presumably with a loop over the characters calling USARTWriteChar.