I2C on eUSCI_B/MSP430FR5739 never fires interrupts while accessing sensor - i2c

I have three INA226 current sensors connected to eUSCI_B, P1.6 and P1.7, on an MSP430FR5739 microcontroller.
My I2C write addr code gives just one NACKIFG, and then forever hangs. On the scope the signals look nearly perfect square, no overshoot and the rise and fall time is 10-20x less than pulse with time of a clock. I use 2k2 Pullups. The wires are about 8cm all together on a PCB.
Previously I even did not manage to get any interrupt, by moving the "UCB0IE |= UCNACKIE | ..." code outside of the UCWRST area, I at least got this one.
#include "i2c.h"
#include "main.h"
#include "uart.h"
#include "ina226.h"
volatile unsigned int RXByte=0;
unsigned char TXData[] ={0, 0, 0, 0}; // Pointer to TX data
unsigned char TXByteCtr=0;
unsigned char TXByteCnt=0;
unsigned char RXByteCnt=0;
volatile unsigned int RXWord=0;
void init_i2c() {
P1SEL1 |= (BIT7 | BIT6);
P1SEL0 &= ~(BIT7 | BIT6);
uart_puts("I2C initialized\n\r");
}
void i2c_write_addr(unsigned int addr, unsigned char byte) {
UCB0CTL1 = UCSWRST; // Enable Module Reset
UCB0CTL0 |= UCMODE_3 | UCMST; // I2C, Master mode, ACLK 12MHz
UCB0CTL1 |= UCSSEL__ACLK;
UCB0BRW = 120;//200; //15; // 24MHz/240 = 100kHz Clock, 24MHz/60 = 400kHz
UCB0I2CSA = addr;
UCB0CTLW1 = UCASTP_2; // Automatic stop and interrupt, reduce deglich to 25 ns
UCB0CTLW0 |= UCTR; //Tranciever
UCB0TBCNT = 1;
UCB0CTL1 &= ~UCSWRST;
UCB0IE |= UCNACKIE | UCTXIE0 | UCRXIE | UCBCNTIE | UCNACKIE | UCSTTIE | UCSTPIE;
TXData[0] = byte;
TXByteCtr = 1; // Load TX byte counter
while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
__bis_SR_register(GIE + CPUOFF); // Enter LPM0 w/ interrupts
uart_puts("i2c_write_addr 6\n\r");
}
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = USCI_B0_VECTOR
__interrupt void USCIB0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCIB0_ISR (void)
#else
#error Compiler not supported!
#endif
{
LED1OUT |= LED1B;
switch(__even_in_range(UCB0IV,0x1E)) {
case 0x00: break; // Vector 0: No interrupts break;
case 0x02: break; // Vector 2: ALIFG break;
case 0x04: // Vector 4: NACKIFG break;
UCB0CTL1 |= UCTXSTT; // Resend I2C start condition
uart_puts("NACKIFG\n\r");
break;
case 0x06: break; // Vector 6: STTIFG break;
case 0x08: break; // Vector 8: STPIFG break;
case 0x0a: break; // Vector 10: RXIFG3 break;
case 0x0c: break; // Vector 14: TXIFG3 break;
case 0x0e: break; // Vector 16: RXIFG2 break;
case 0x10: break; // Vector 18: TXIFG2 break;
case 0x12: break; // Vector 20: RXIFG1 break;
case 0x14: break; // Vector 22: TXIFG1 break;
case 0x16: // Vector 24: RXIFG0 break;
RXByte = UCB0RXBUF; // Get RX data
RXWord = RXWord <<8;
RXWord |= RXByte;
uart_puts("RXIFG0\n\r");
break;
case 0x18: // Vector 26: TXIFG0 break;
if (TXByteCtr) // Check TX byte counter
{
TXByteCtr--;
UCB0TXBUF = TXData[TXByteCtr]; // Load TX buffer
}
else
{
//UCB0IFG &= ~UCTXIFG; // Clear USCI_B0 TX int flag
//UCB0CTLW0 |= UCTXSTP;
__bic_SR_register_on_exit(CPUOFF);// Exit LPM0
}
uart_puts("TXIFG0\n\r");
break;
case 0x1a: // Vector 28: BCNTIFG break;
uart_puts("BCNTIFG\n\r");
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
break;
case 0x1c: // Vector 30: clock low timeout break;
LED1OUT ^= LED1B;
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
uart_puts("CLKLOWTO\n\r");
break;
case 0x1e: break; // Vector 32: 9th bit break;
default: break;
}
}
And my stripped down main.c
void configure_clock()
{
FRCTL0 = FWPW | NACCESS_2 | NPRECHG_1; // Change the NACCESS_x value to add the right amount of waitstates
// Configure Clock System
CSCTL0_H = CSKEY >> 8; // Unlock CS registers
CSCTL1 = DCOFSEL_3 | DCORSEL; // Set DCO = 24MHz
CSCTL2 = SELA__DCOCLK | SELS__DCOCLK | SELM__DCOCLK;// Set ACLK=VLO SMCLK=DCO
CSCTL3 = DIVA__2 | DIVS__1 | DIVM__2; // Set all dividers (A=12MHz, S=24MHz, M=12MHz)
CSCTL0_H = 0; // Lock CS registers
}
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
configure_clock();
//Configure Debug UART
init_uart_115200();
// Disable the GPIO power-on default high-impedance mode to activate
// previously configured port settings
PM5CTL0 &= ~LOCKLPM5;
//Configure i2c
init_i2c();
_enable_interrupts();
i2c_write_addr(U3_ADDR, 0xFE); // Already stops here
uart_puts("INA216 ID: ");
uart_puti(i2c_read_uint(U3_ADDR));
while (1) {}
}

Related

UART interrupt on ARM Cortex-M0 not triggering while utilizing FreeRTOS

I am using an STM32F0 with the following std_periph_lib api functions to configure and execute a UART transmit from a FreeRTOS queue.
// Initialization
{
USART_InitTypeDef usart_init;
USART_StructInit(&usart_init);
usart_init.USART_BaudRate = 9600;
USART_Init(s_port[uart].base, &usart_init);
USART_ClearITPendingBit(USART1, USART_FLAG_TXE);
USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
NVIC_InitTypeDef init_struct = {
.NVIC_IRQChannel = USART1_IRQn,
.NVIC_IRQChannelPriority = 0,
.NVIC_IRQChannelCmd = ENABLE,
};
NVIC_Init(&init_struct);
}
// Transmit
// Write all passed data to queue
for (uint8_t i = 0; i < len; i++) {
if (queue_send(&queue, &data[i], 0) != pdTRUE) {
break;
}
}
if (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == SET) {
uint8_t tx_data = 0;
// get first byte from queue to initiate transmission
UBaseType_t cmpl = queue_receive(&queue, &tx_data, 0);
if (cmpl == pdFALSE) { // No data left in queue
USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
return status;
}
// Send first byte
USART_SendData(USART1, tx_data);
// Enable TX Interrupts to begin transmission
USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
}
I have confirmed that the data is received from the queue, and that the USART_SendData and USART_ITConfig execute, but the isr:
void USART1_IRQHandler(void) {
}
is never executed. Does anyone know what may be causing this?
I have read the FreeRTOS docs concerning ARM interrupt structure (here) and have confirmed that my ISR is at a lower logical priority than configMAX_SYSCALL_INTERRUPT_PRIORITY and higher than configKERNEL_INTERRUPT_PRIORITY.

STM32 I2C scan returns different addresses than Arduino

Good day
The goal is to use the LSM9DS0 with a ST chip.
The situation is that the I2C address as returned by the scanner (ST environment) is not the same to that of Arduino I2C scanner. I am using a STM32 Nucleo-F429 and ESP32 devkit.
When I scan for I2C addresses using the below code, it returns the following four addresses:
0x3A
0x3B
0xD6
0xD7
However I have used this very IMU breakout on a ESP32 before and I noticed that the addresses are not the same. When I run the I2C scanning code I get the following addresses.
0x1D
0x6B
STM32 code: Src files were generated by CubeMX. Let me know if the i2c.h/c are required. But they should be pretty standard.
for (uint16_t i = 0; i < 255; i++)
{
if (HAL_I2C_IsDeviceReady(&hi2c1, i, 5, 50) == HAL_OK)
{
HAL_GPIO_TogglePin(LED_RED_PORT, LED_RED_PIN);
char I2cMessage[10];
sprintf(I2cMessage, "%d , 0x%X\r\n", i, i);
HAL_UART_Transmit(&huart2, (uint8_t *)I2cMessage, strlen(I2cMessage), 10);
}
}
Arduino code:
#include <Wire.h>
void setup()
{
Wire.begin();
Serial.begin(115200);
while (!Serial); // Leonardo: wait for serial monitor
Serial.println("\nI2C Scanner");
}
void loop()
{
byte error, address;
int nDevices;
Serial.println("Scanning...");
nDevices = 0;
for(address = 1; address < 127; address++ )
{
// The i2c_scanner uses the return value of
// the Write.endTransmisstion to see if
// a device did acknowledge to the address.
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0)
{
Serial.print("I2C device found at address 0x");
if (address<16)
Serial.print("0");
Serial.print(address,HEX);
Serial.println(" !");
nDevices++;
}
else if (error==4)
{
Serial.print("Unknown error at address 0x");
if (address<16)
Serial.print("0");
Serial.println(address,HEX);
}
}
if (nDevices == 0)
Serial.println("No I2C devices found\n");
else
Serial.println("done\n");
delay(5000); // wait 5 seconds for next scan
}
Does anyone know why this is and is it a problem?
I found the answer in the description of the HAL API. The API requires the 7bt address to be bit shifted to the left by 1bit.
Within the file: stm32F4xx_hal_i2c.c the description of the HAL_I2C_IsDeviceReady() API says the following:
* #param DevAddress Target device address: The device 7 bits address value
* in datasheet must be shifted to the left before calling the interface
Thus, change the IsDeviceReady arguments as follows and it will work.
for (uint16_t i = 0; i < 255; i++)
{
if (HAL_I2C_IsDeviceReady(&hi2c1, i<<1, 5, 10) == HAL_OK)
{
// Do crazy stuff
}
}
This worked for me. Hope it helps anyone with the same issue
one can find I2C devices on an ESP32 using the code below:
void I2Cscanner() {
Serial.println ();
Serial.println ("I2C scanner. Scanning ...");
byte count = 0;
Wire.begin();
for (byte i = 8; i < 120; i++)
{
Wire.beginTransmission (i); // Begin I2C transmission Address (i)
if (Wire.endTransmission () == 0) // Receive 0 = success (ACK response)
{
Serial.print ("Found address: ");
Serial.print (i, DEC);
Serial.print (" (0x");
Serial.print (i, HEX); // PCF8574 7 bit address
Serial.println (")");
count++;
}
}
Serial.print ("Found ");
Serial.print (count, DEC); // numbers of devices
Serial.println (" device(s).");
}

Not able to read from an external EEPROM using the STM32F103C8

I'm trying to write and read from an external EEPROM. There is a start bit (SB) followed by an opcode, then a 6-bit address and then the actual data. I've combined the SB and opcode into one byte that I can send as a start condition. I'm able to enable, erase and then write to the EEPROM. I'm assuming this is working since the HAL functions return HAL_OK and I can see the valid waveforms on the scope.
What I can't seem to do is read the data back. For the READ operation I don't see any waveforms on the scope. The number of clock cycles required is odd-numbered and not in multiples of 8. I don't know how I can send odd number of clock cycles since all the data is either 8, 16 or 32-bit. Wherever there are 25 or 29 clock cycles need, I seem to be sending 32 and where the required cycles are 9, I seem to be sending 16. I'm really hoping to avoid bit-banging as suggested in this thread.
Here is the main code:
int main(void)
{
HAL_Init();
MX_GPIO_Init();
MX_SPI1_Init();
__HAL_SPI_ENABLE(&hspi1);
// pull the CS pin high to select the EEPROM (active HIGH)
HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET);
HAL_Delay(10);
// Enable the EEPROM
enable_status = Enable_EEPROM(&EEPROM_SPI_PORT);
HAL_Delay(10);
// Erase the value at address 0x00
erase_status = Erase_EEPROM(&EEPROM_SPI_PORT, addr);
HAL_Delay(10);
// Write data 0xABCD at addr 0x00
write_status = Write_EEPROM(&EEPROM_SPI_PORT, addr, tx_data);
HAL_Delay(10);
// Disabling the EEPROM (with an EWDS) after a WRITE as described in the datasheet
disable_status = Disable_EEPROM(&EEPROM_SPI_PORT);
HAL_Delay(10);
// Re-enabling it
enable_status = Enable_EEPROM(&EEPROM_SPI_PORT);
HAL_Delay(10);
// Read from the EEPROM. This part isn't working.
read_status = Read_EEPROM(&EEPROM_SPI_PORT, addr, rx_data);
HAL_Delay(10);
// Pull the CS pin low to deselect the chip again.
HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET);
while (1)
{
}
}
The SPI is initialized to handle 16-bit data values
SPI_HandleTypeDef hspi1;
/* SPI1 init function */
void MX_SPI1_Init(void)
{
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_16BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
These are the EEPROM functions
#define ERASE 0x07 // erase specific memory location. This is followed by the 8-bit address and then by the 16-bit data.
#define READ 0x06 // read the memory location.
#define WRITE 0x05 // write to the memory location
#define EEPROM_SPI_PORT hspi1
extern SPI_HandleTypeDef EEPROM_SPI_PORT;
//Enable the EEPROM
//Accepts: SPI handle
//Returns: Success or failure of the enable operation
uint8_t Enable_EEPROM (SPI_TypeDef *spi_handle) {
uint16_t ewen = (0x04 << 8) | 0b00110000;
if (HAL_SPI_Transmit(spi_handle, &ewen, 1, HAL_MAX_DELAY) == HAL_OK) return TRUE;
else return FALSE;
}
//Disable the EEPROM
//Accepts: SPI handle
//Returns: Success or failure of the disable operation
uint8_t Disable_EEPROM (SPI_TypeDef *spi_handle) {
uint16_t ewds = (0x04 << 8) | 0b00000000;
if (HAL_SPI_Transmit(spi_handle, &ewds, 1, HAL_MAX_DELAY) == HAL_OK) return TRUE;
else return FALSE;
}
//Read from the EEPROM
//Accepts: SPI handle, memory address and data buffer where the read value will be stored
//Returns: Success or failure of read operation
uint8_t Read_EEPROM (SPI_TypeDef *spi_handle, uint8_t addr, uint16_t data) {
uint16_t write_package;
write_package = (READ << 8 | addr);
// if (HAL_SPI_Transmit(spi_handle, &write_package, 1, HAL_MAX_DELAY) == HAL_OK) {
// HAL_Delay(10);
// if (HAL_SPI_Receive(spi_handle, &data, 1, HAL_MAX_DELAY) == HAL_OK) return TRUE;
// else return FALSE;
// }
if (HAL_SPI_TransmitReceive(spi_handle, &write_package, &data, 1, HAL_MAX_DELAY) == HAL_OK) return TRUE;
else return FALSE;
}
//Write to the EEPROM
//Accepts: SPI handle, memory address and data to be written
//Returns: Success or failure of write operation
uint8_t Write_EEPROM (SPI_TypeDef *spi_handle, uint8_t addr, uint16_t data) {
uint16_t write_package[2];
write_package[0] = (WRITE << 8 | addr);
write_package[1] = data;
if (HAL_SPI_Transmit(spi_handle, write_package, 2, HAL_MAX_DELAY) == HAL_OK) return TRUE;
else return FALSE;
}
//Erase a specific memory address from the EEPROM
//Accepts: SPI handle and the memory address to be erased
//Returns: Success or failure of erase operation
uint8_t Erase_EEPROM (SPI_TypeDef *spi_handle, uint8_t addr) {
uint16_t write_package;
write_package = (ERASE << 8 | addr);
if (HAL_SPI_Transmit(spi_handle, &write_package, 1, HAL_MAX_DELAY) == HAL_OK) return TRUE;
else return FALSE;
}
EDIT: I’ve attached waveforms here as well.
Enable
Erase
Write
Without looking through your code in detail, I've spotted a possible problem: In order to complete an SPI operation, the chip select (CS) line usually needs to be pulled low before and set high again after every operation.
So, the EEPROM functions in your driver code probably need to first set the CS pin low, do some SPI operation, and set it high again after that.
For convenience, I usually add some simple helper functions to the driver source file:
static GPIO_TypeDef *_cs_port;
static uint16_t _cs_pin;
static void _chip_select(void)
{
HAL_GPIO_WritePin(_cs_port, _cs_pin, GPIO_PIN_RESET);
}
static void _chip_deselect(void)
{
HAL_GPIO_WritePin(_cs_port, _cs_pin, GPIO_PIN_SET);
}
In that case, I usually intialize the driver and and keep track of the peripheral instance and chip select GPIO, similar to this:
static SPI_HandleTypeDef *_spi;
static uint8_t _init = 0;
int8_t eeprom_init(
SPI_HandleTypeDef *spi,
GPIO_TypeDef *gpio_cs_port,
uint16_t gpio_cs_pin)
{
if (_init)
return -1;
_spi = spi;
_cs_port = gpio_cs_port;
_cs_pin = gpio_cs_pin;
/* do initialization here */
_chip_deselect();
_init = 1;
return 0;
}
int8_t eeprom_clear(void)
{
if (!_init)
return -1;
/* do de-initialization here */
_spi = 0;
_cs_port = 0;
_cs_pin = 0;
_init = 0;
return 0;
}
int8_t eeprom_op_x(void)
{
if (!_init)
return -1;
_chip_select();
op_x(); /* todo */
_chip_deselect();
return 0;
}
I hope this helps :) ! There might be other issues in your hardware/software; this is probably not the full solution to your problem.
BTW: There are also ways to use hardware chip select (STM32 SPI peripheral), which I've never used (SPI / NSS in the reference manual). As far as I can tell, you also used SPI_NSS_SOFT in your SPI configuration, which requires you to manually set the chip select line.
BTW: Unrelated, but maybe of interest: ST provides simple HAL functions to access external I2C flash (HAL_I2C_Mem_*() functions).
edit 0 (more findings by skimming through code / datasheet):
Read_EEPROM() will not work like this, the data read from the bus isn't accessible outside the function's scope (C issue). Instead, a pointer to a read buffer could be passed to the function (or the read data could be returned as return value). For example like this: uint8_t Read_EEPROM (SPI_TypeDef *spi_handle, uint8_t addr, uint8_t *data, uint8_t byte_count)
In Read_EEPROM(): HAL_SPI_TransmitReceive() won't read the incoming bytes, when used like this. It receives and transmits at the same time. So it would make sense to first write the read / address command, and then start reading the incoming bytes (like in your code that has been commented out).
In Enable_/Disable_/Read_/Erase_EEPROM(): The number of bytes (size) seems to be wrong, it should be 2 instead of 1, in order to make HAL_SPI_Transmit() / HAL_SPI_TransmitReceive() transmit/receive the right number of bytes.
This IC does not seem to be well suited to be used with normal
SPI, since it requires a very specific bit sequence which is
not byte aligned (like you said). It might make sense to bit bang
the communication (like you've mentioned), and pay attention to every
little bit stated in the datasheet...
Since this seems to be an early test, I'd try to keep it as simple as possible, and get a first enable/write/read operation going, by bit-twiddling the same SPI pins by hand (reconfigured as normal GPIOs), so that the problems with the STM32's byte oriented SPI HAL functions won't get in your way. And then work towards a nice little driver... Maybe the STM32's SPI can still be used in some way, it's hard to tell for me right now...

A strange thing about serial communication between Arduino and Matlab

I am new to Arduino and Matlab. Recently I am doing a project with Arduino and Matlab, and I found a strange thing when I try to send some data to Arduino from Matlab.
Here is my code
delete(instrfind({'Port'},{'COM3'}))
clear all
s = serial('COM3','BaudRate',9600);
% set(s,'BytesAvailableFcnCount',10);
set(s,'Terminator','CR');
fopen(s);
% sss=input('Enter led value 1 or 2 (1=ON, 2=OFF, 0=EXIT PROGRAM): ');
sss=2 ;
fwrite(s,sss,'char');
ss = fscanf(s,'%s');
ss
fclose(s);
and i get this
and when I cancel the comment of the sss=input line, whatever I type in the data send successfully. like this:
I want know HOW can I send a data to my Arduino without any input action.
Here is the Arduino code
int incomingByte = 0;
int motor2= 2 ;
int motor3= 3 ;
int motor4= 4 ;
int motor5= 5 ;
int motor6= 6 ;
int motor7= 7 ;
int motor8= 8 ;
int motor9= 9 ;
int matlabSignal;
int motorDir= 30 ;
void setup() {
// put your setup code here, to run once:
pinMode(motor2,OUTPUT);
pinMode(motor3,OUTPUT);
pinMode(motor4,OUTPUT);
pinMode(motor5,OUTPUT);
pinMode(motor6,OUTPUT);
pinMode(motor7,OUTPUT);
pinMode(motor8,OUTPUT);
pinMode(motor9,OUTPUT);
//en pin
pinMode(motorDir,OUTPUT);
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
if(Serial.available()>0){
incomingByte = Serial.read();
Serial.println(incomingByte,DEC);
matlabSignal = incomingByte;
}
/*
digitalWrite(motor2,HIGH);
digitalWrite(motor3,HIGH);
digitalWrite(motor4,HIGH);
*/
switch (matlabSignal){
case 1:
digitalWrite(motor9,HIGH);
break;
case 2:
digitalWrite(motor2,HIGH);
break;
case 3:
digitalWrite(motor3,HIGH);
break;
case 4:
digitalWrite(motor4,HIGH);
break;
case 5:
digitalWrite(motor5,HIGH);
break;
case 6:
digitalWrite(motor6,HIGH);
break;
case 7:
digitalWrite(motor7,HIGH);
break;
case 8:
digitalWrite(motor8,HIGH);
break;
}
}

ADXL345 atmega16

i just started the project which requiers to connect ADXL345 to my Atmega16. I want to put device id on screen and read axis. So far i cant communicate with ADXL345. ON LCD only appears 0 I would be gratefull for any help.
#include <avr/io.h>
#include <stdlib.h>
#include <util/delay.h>
#include "hd44780.h"
#define F_CPU 1000000UL
/*-----------------------Rejestry ADXL345---------------------*/
char POWER_CTL = 0x2D; //Power Control Register 0x08 measurement
char DATA_FORMAT = 0x31;
char BW_RATE = 0X2C;
char FIFO = 0x38; //fifo ctl
char DATAX0 = 0x32; //X-Axis Data 0
char DATAX1 = 0x33; //X-Axis Data 1
char DATAY0 = 0x34; //Y-Axis Data 0
char DATAY1 = 0x35; //Y-Axis Data 1
char DATAZ0 = 0x36; //Z-Axis Data 0
char DATAZ1 = 0x37; //Z-Axis Data 1
char DEVICEID = 0x00;
#define Read_Byte_SPI( addr ) ADXL_write( 0x80 | addr , 0xFF );
/*------------------PORTY SPI---------------*/
#define SPI_CS PB4
#define DDR_SPI DDRB
#define DD_MOSI PB5
#define DD_MIOS PB6
#define DD_SCK PB7
/*vcc<->vs*/
//--------------------------------------Funkcje-------------------
unsigned int init_port(void) //ports 4 lcd
{DDRD =0x00; PORTD =0x07 ; }
/*function 4 lcd*/
static void lcd( int a){ LCD_LOCATE(2,0); char buff[2]; char tab[2]; /*itoa(a,buff,10);*/ sprintf(a, %d", buff); lcd_puts(buff);
}
/**
* This writes to a register with the data passed to the address passed
* #param unsigned char cReg - the address of the register you wish to write to
* #param unsigned char cData - the data you wish to write to the register
*/
unsigned char ADXL_write(unsigned char cReg, unsigned char cData){
set_spics();
/* Start transmission send register */
SPDR = cReg;
/* Wait for transmission complete */
while(!(SPSR & (1<<SPIF)))
{ /* NOOP */ }
SPDR = cData;
/* Wait for transmission complete */
while(!(SPSR & (1<<SPIF)))
{ /* NOOP */ }
clear_spics();
return SPDR;
}
uint8_t ADXL_read(unsigned char addr) { // read ADXL345 - 128+ addrs, back 8 bits - found this in another topic
int8_t ans;
set_spics();
SPDR = 0x08 | addr;
loop_until_bit_is_set(SPSR, SPIF);
SPDR = 0xFF;
loop_until_bit_is_set(SPSR, SPIF);
ans = SPDR;
clear_spics();
return(ans);}
//inicjalizacjia SPI
void Init_SPI(){
// make the MOSI, SCK, and SS pins outputs
DDRB |= ( 1 << DD_MOSI ) | ( 1 << DD_SCK ) | ( 1 << SPI_CS );
DDRB &= ~( 1 << DD_MIOS );
/* Enable SPI, Master, set clock rate fck/128 */
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<SPR1);
}
//Control SS=CHIP SELECT ADXL345
void clear_spics(){
PORTB |= _BV(SPI_CS); // high
_delay_ms(30);}
void set_spics(){
PORTB &=~ _BV(SPI_CS); // low
_delay_ms(30);}
void ADXL_init(void){
//init ADXL
ADXL_write(DATA_FORMAT,0x08); //pełna rozdzielczość DATASHEET STRONA 26 4SPI
ADXL_write(BW_RATE, 0x0A) ; //100hz
ADXL_write(POWER_CTL,0x08);
ADXL_write(FIFO, 0); //FIFO Wylacozny
}
/*------------------------główna petla---------------------------*/
int main(void)
{
/* tab for strings */
char str1[] = "Czujnik ADXL 345";
/* init lcd*/
lcd_init();
/* LCD UP */
LCD_DISPLAY(LCDDISPLAY);
LCD_CLEAR;
LCD_LOCATE(1,1);
lcd_puts(str1);
init_port();/*port init*/
Init_SPI();//SPIUP
_delay_ms(50);
ADXL_init(); //ADXL345 config
_delay_ms(50);
while(1)
{
int8_t k;
k=Read_Byte_SPI( DEVICEID );
lcd(k);
_delay_ms(5000);
k=ADXL_read(DATAX0);
lcd(k);
_delay_ms(5000);
}
`>