8051 MCU I2C signals do not respond - i2c

I got stuck on I2C communication issue and I need your help
Currently, I'm using the microcontroller (MCU) C8051F130. I need to communicate between MCU and a sensor via I2C.
As I know, the I2C on this MCU can be enabled by the bit ENSMB in the register SMB0CN. But when I set that bit to 1 and check SMB0CN status in IDE debug mode, I see it always SMB0CN = 0x00. It means I2C is still not enabled. As a result, the I2C SDA & SCL signals on MCU output always high status.
I also checked pull-up resistor on SDA & SCL MCU ports, they're connected to resistor 10KOhm. I think it should be fine.
Here's my code for I2C register setting & send/receive/acknowledge. Please give me suggestion.
#define SMB0_PAGE 0x00 /* SMBUS 0 */
void main()
{
SMBUS_Initial();
}
// I2C SFR setting
void SMBUS_Initial()
{
unsigned char SFRPAGE_BUF; // SFR page of SMB0CN is 0
SFRPAGE_BUF = SFRPAGE;
SFRPAGE = SMB0_PAGE;
/*
BUSY = 0;
// AA = 1;
STA = 1;
STO = 1;*/
ENSMB = 1;
SFRPAGE = SFRPAGE_BUF;
}
sfr SMB0CN = 0xC0; /* SMBUS 0 CONTROL */
/* SMB0CN 0xC0 */
sbit BUSY = SMB0CN ^ 7; // SMBUS 0 BUSY
sbit ENSMB = SMB0CN ^ 6; // SMBUS 0 ENABLE
sbit STA = SMB0CN ^ 5; // SMBUS 0 START FLAG
sbit STO = SMB0CN ^ 4; // SMBUS 0 STOP FLAG
sbit SI = SMB0CN ^ 3; // SMBUS 0 INTERRUPT PENDING FLAG
sbit AA = SMB0CN ^ 2; // SMBUS 0 ASSERT/ACKNOWLEDGE FLAG
sbit SMBFTE = SMB0CN ^ 1; // SMBUS 0 FREE TIMER ENABLE
sbit SMBTOE = SMB0CN ^ 0;
// I2C communication
void I2C_START()
{
unsigned char SFRPAGE_BUF;
SFRPAGE_BUF = SFRPAGE;
SFRPAGE = CONFIG_PAGE;
Delay2us(6);
I2C_SDA = 1;
Delay2us(2);
I2C_SCL = 1;
Delay2us(8);
I2C_SDA = 0;
Delay2us(5);
I2C_SCL = 0;
Delay2us(5);
SFRPAGE = SFRPAGE_BUF;
}
//=======================================================================================
// I2C_1 Ack by slave
//=======================================================================================
void I2C_ACK(void)
{
unsigned char SFRPAGE_BUF;
SFRPAGE_BUF = SFRPAGE;
SFRPAGE = CONFIG_PAGE;
Delay2us(3);
I2C_SDA = 1;
Delay2us(1);
I2C_SCL = 1;
Delay2us(3);
if(!I2C_SDA)
// ACK_f = 1;
Delay2us(2);
I2C_SCL = 0;
Delay2us(1);
I2C_SDA = 0;
Delay2us(5);
SFRPAGE = SFRPAGE_BUF;
}
// I2C_1 Ack by master
//=======================================================================================
void I2C_ACK_master()
{
unsigned char SFRPAGE_BUF;
SFRPAGE_BUF = SFRPAGE;
SFRPAGE = CONFIG_PAGE;
I2C_SDA = 0;
I2C_SCL = 1;
Delay2us(1);
I2C_SCL = 0;
I2C_SDA = 1;
SFRPAGE = SFRPAGE_BUF;
}
void I2C_NAK()
{
unsigned char SFRPAGE_BUF;
SFRPAGE_BUF = SFRPAGE;
SFRPAGE = CONFIG_PAGE;
I2C_SDA = 1;
I2C_SCL = 1;
Delay2us(1);
I2C_SCL = 0;
I2C_SDA = 1;
SFRPAGE = SFRPAGE_BUF;
}
//=======================================================================================
// I2C Start
//=======================================================================================
//=======================================================================================
// I2C Stop
//=======================================================================================
void I2C_STOP(void)
{
unsigned char SFRPAGE_BUF;
SFRPAGE_BUF = SFRPAGE;
SFRPAGE = CONFIG_PAGE;
I2C_SCL = 0;
I2C_SDA = 0;
Delay2us(8);
I2C_SCL = 1;
Delay2us(5);
I2C_SDA = 1;
SFRPAGE = SFRPAGE_BUF;
}
// I2C Tx
//=======================================================================================
void I2C_TX(unsigned char Tx_data)
{
unsigned char x;
unsigned char SFRPAGE_BUF;
SFRPAGE_BUF = SFRPAGE;
SFRPAGE = CONFIG_PAGE;
for(x=0;x<8;x++)
{
I2C_SCL = 0;
Delay2us(1);
if(Tx_data & 0x80)
I2C_SDA = 1;
else
I2C_SDA = 0;
Tx_data <<= 1;
Delay2us(1);
I2C_SCL = 1;
Delay2us(2);
}
I2C_SCL = 0;
SFRPAGE = SFRPAGE_BUF;
}
//=======================================================================================
// I2C Rx
//=======================================================================================
unsigned char I2C_RX(unsigned char I2C_ACK)
{
unsigned char x;
unsigned char Rx_Data, I2C_rx_buf;
unsigned char SFRPAGE_BUF;
SFRPAGE_BUF = SFRPAGE;
SFRPAGE = CONFIG_PAGE;
I2C_SDA = 1;
// Delay2us(10);
Delay2us(2);
for(x=0;x<8;x++)
{
I2C_rx_buf <<= 1;
do{
I2C_SCL = 1;
}while(I2C_SCL == 0);
Delay2us(1);
if(I2C_SDA)
I2C_rx_buf |= 1;
I2C_SCL = 0;
}
if(I2C_ACK)
I2C_SDA = 0;
else
I2C_SDA = 1;
Delay2us(2);
I2C_SCL = 0;
I2C_SDA = 1;
return I2C_ACK;
SFRPAGE = SFRPAGE_BUF;
}
///// Configuration register ///////////
void ALS_config(unsigned char slave_write,unsigned char dataA,unsigned char dataB)
{
I2C_START();
I2C_TX(slave_write);
I2C_ACK();
I2C_TX(0x01);
I2C_ACK();
I2C_TX(dataA);
// I2C_RX();
I2C_ACK();
I2C_TX(dataB);
// I2C_RX();
I2C_ACK();
I2C_STOP();
}
unsigned int MCU_read(unsigned char slave_write,unsigned char slave_read)
{
unsigned char i, ALS_MSB, ALS_LSB, DSI_val[52];
unsigned int ALS_lux;
// High-speed I2C ////
I2C_START();
I2C_TX(0x08);
I2C_NAK();
/////////////////
////// Partial write ////////
I2C_START();
I2C_TX(slave_write);
I2C_ACK();
I2C_TX(0x00);
I2C_ACK();
I2C_STOP();
delay1m(1);
//////////////// Read from ALS /////////////////////////////
I2C_START();
I2C_TX(slave_read);
I2C_ACK();
I2C_RX(I2C_ACK);
I2C_ACK_master();
ALS_MSB = I2C_rx_buf;
// ALS_MSB = ALS_MSB&0x0F;
// ALS_MSB = I2C_rx_buf<<8;
delay1m(3);
I2C_RX(I2C_ACK);
I2C_ACK_master();
I2C_NAK();
ALS_LSB = I2C_rx_buf;
I2C_STOP();
ALS_lux = ALS_MSB | ALS_LSB;
return ALS_lux;
}
void low_limit_ALS(unsigned char slave_write,unsigned char low_limit_MSB,unsigned char low_limit_LSB)
{
I2C_START();
I2C_TX(slave_write);
I2C_ACK();
I2C_TX(0x02);
I2C_ACK();
I2C_TX(low_limit_MSB);
// I2C_RX();
I2C_ACK();
I2C_TX(low_limit_LSB);
// I2C_RX();
I2C_ACK();
I2C_STOP();
}
void high_limit_ALS(unsigned char slave_write,unsigned char high_limit_MSB,unsigned char high_limit_LSB)
{
I2C_START();
I2C_TX(slave_write);
I2C_ACK();
I2C_TX(0x03);
I2C_ACK();
I2C_TX(high_limit_MSB);
// I2C_RX();
I2C_ACK();
I2C_TX(high_limit_LSB);
// I2C_RX();
I2C_ACK();
I2C_STOP();
}

Related

Including git hub library in Arduino IDE

I am trying to record sound with an ada fruit SPH6045 microphone and a Raspberry Pi Pico. I am following this git hub page however when I open the main.cpp code in Arduino IDE and compile I am getting the following error.
C:\Users\Brett J\Documents\Arduino\Rasbery Pi mic\Rasbery Pi mic.ino:10:10: fatal error: sph0645.pio.h: No such file or directory
10 | #include "sph0645.pio.h"
| ^~~~~~~~~~~~~~~
compilation terminated.
exit status 1
Compilation error: sph0645.pio.h: No such file or directory
I downloaded and extracted the zip file and saved it in the arduino librarys folder but that did not work. So then I tried to save it in the folder it is looking for it in and still no luck. I am new to raspberry pi's but am very familiar with the arduino IDE.The code is as follows.
#include "pico/time.h"
#include "pico/stdlib.h"
#include <stdio.h>
#include <inttypes.h>
#include <vector>
#include "hardware/clocks.h"
#include "hardware/pio.h"
#include "hardware/spi.h"
#include "hardware/uart.h"
#include "sph0645.pio.h"
#include <algorithm>
#include "hardware/dma.h"
#define PIN_DATA_OUT 2
#define PIN_SCLK 3
#define PIN_WS 4
#define printu(var) printf("%s: %lu\n", (#var), (size_t) (var))
#define bswap(x) \
((((x) & 0xff000000u) >> 24) | (((x) & 0x00ff0000u) >> 8) \
| (((x) & 0x0000ff00u) << 8) | (((x) & 0x000000ffu) << 24))
size_t clk;
PIO pio = pio0;
uint sm;
uint dma_chan;
#define BLOCK_SIZE (48000)
void init() {
stdio_uart_init_full(uart0, 921600, 0, 1);
/* stdio_init_all(); */
clk = clock_get_hz(clk_sys);
dma_chan = dma_claim_unused_channel(true);
}
static void start_dma(int32_t* buf, size_t len) {
dma_channel_config c = dma_channel_get_default_config(dma_chan);
channel_config_set_read_increment(&c, false);
channel_config_set_write_increment(&c, true);
channel_config_set_dreq(&c, pio_get_dreq(pio, sm, false));
dma_channel_configure(dma_chan, &c, buf, &pio->rxf[sm], len, true);
}
static void finalize_dma() {
dma_channel_wait_for_finish_blocking(dma_chan);
}
static void print_samples(int32_t* samples, size_t len) {
for (size_t i = 0; i < len; i++) {
auto val = samples[i];
printf("%d\t%X\n", val, val);
}
/* printf("("); */
/* for (size_t i = 0; i < len; i++) { */
/* printf("%d, ", samples[i]); */
/* /1* printf("%08X, ", samples[i]); *1/ */
/* } */
/* printf(")\n"); */
}
static void normalize(int32_t* samples, size_t len) {
for (int i = 0; i < 10; i++) {
start_dma(samples, len);
finalize_dma();
}
}
int main() {
init();
auto offset = pio_add_program(pio, &i2s_program);
sm = pio_claim_unused_sm(pio, true);
i2s_program_init(pio, sm, offset, PIN_DATA_OUT, PIN_SCLK);
/* start_dma(samples, BLOCK_SIZE); */
/* finalize_dma(); */
/* normalize(samples, BLOCK_SIZE); */
int32_t samples[BLOCK_SIZE] = {0};
auto start_time = time_us_32();
for (size_t i = 0; i < BLOCK_SIZE; i++) {
uint32_t val = pio_sm_get_blocking(pio, sm);
samples[i] = *((int32_t *) &val);
}
/* printf("%lu\n", time_us_32() - start_time); */
/* for (size_t i = 0; i < BLOCK_SIZE; i++) { */
/* samples[i] = pio_sm_get_blocking(pio, sm); */
/* } */
print_samples(samples, BLOCK_SIZE);
return 0;
}`
https://github.com/vijaymarupudi/sph0645-pico-troubleshooting

PWM input capture and repeat. STM32F4

guys.
I generated PWM signal with timer TIM1.
I want get this PWM from TIM1 with timer TIM2 and repeat it on the some GPIO pin.
I used Standart Peripheral Library.
PWM has generated on pin PA8 with timer TIM1 successfully, but i can't receive this PWM signal from PA0 pin with TIM2.
(PA8 и PA0 i connected with cable.)
Help me, please.
type here
#include "stm32f4xx.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_tim.h"
#include "misc.h"
#include <stdio.h>
GPIO_InitTypeDef GPIO_InitStruct;
TIM_TimeBaseInitTypeDef TIM1_TimeBaseStruct;
TIM_OCInitTypeDef TIM1_OCInitStruct;
TIM_ICInitTypeDef TIM_ICInitStruct;
volatile uint16_t capture1 = 0, capture2 = 0;
volatile uint8_t capture_is_first = 1, capture_is_ready = 0;
const uint32_t myPeriod = 61538 - 1;
const uint32_t myPrescaler = 1 - 1;
const uint32_t myPulse = 5000;
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
// Generate PWM on PA8
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// Input capture PWM on PA0
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_TIM1);
TIM1_TimeBaseStruct.TIM_Period = myPeriod;
TIM1_TimeBaseStruct.TIM_Prescaler = myPrescaler;
TIM1_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM1, &TIM1_TimeBaseStruct);
TIM1_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;
TIM1_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;
TIM1_OCInitStruct.TIM_Pulse = myPulse;
TIM1_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;
TIM1_OCInitStruct.TIM_OCNPolarity = TIM_OutputState_Disable;
TIM1_OCInitStruct.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OC1Init(TIM1, &TIM1_OCInitStruct);
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM1, ENABLE);
TIM_CtrlPWMOutputs(TIM1, ENABLE);
TIM_Cmd(TIM1, ENABLE);
TIM_TimeBaseInitTypeDef timer_base;
TIM_TimeBaseStructInit(&timer_base);
timer_base.TIM_Prescaler = 24000 - 1;
TIM_ICInitTypeDef timer_ic;
timer_ic.TIM_Channel = TIM_Channel_1;
timer_ic.TIM_ICPolarity = TIM_ICPolarity_Rising;
timer_ic.TIM_ICSelection = TIM_ICSelection_DirectTI;
timer_ic.TIM_ICPrescaler = TIM_ICPSC_DIV1;
timer_ic.TIM_ICFilter = 0;
TIM_ICInit(TIM2, &timer_ic);
TIM_ITConfig(TIM2, TIM_IT_CC1, ENABLE);
NVIC_EnableIRQ(TIM2_IRQn);
/* Включаем таймер */
TIM_Cmd(TIM2, ENABLE);
while (1)
{
}
} // main
void TIM2_IRQHandler(void)
{
int i = 0;
i++;
printf("I'm TIM2 IRQ Handler.");
if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);
capture1 = capture2;
capture2 = TIM_GetCapture1(TIM2);
if (!capture_is_first)
capture_is_ready = 1;
capture_is_first = 0;
if (TIM_GetFlagStatus(TIM2, TIM_FLAG_CC1OF) != RESET)
{
TIM_ClearFlag(TIM2, TIM_FLAG_CC1OF);
// ...
}
}
}
I wrote the receive (input capture) PWM signal code using examples from the Internet, but i can't debug this. Help please. I'm new to embedded dev.

I2C doesn't work after uploading (only sometimes)

I wrote a little program that reads I2C values with interrupts: The Problem is that sometimes it just doesn't work after uploading. I just have to run it so many times until it works (not changing anything in the code). It seems like its just coincidence if it works or not.
Here are the Details:
Sensor: HMC 5983 or MPU-6050 (same problem)
Board: STM32F103RB (Nucleo 64)
Code (without the generated Cubemx stuff):
int main(void) {
/*/////////////////////Setup/////////////////////////*/
buf[0] = 0x00;
buf[1] = 0x78;
buf[2] = 0x80;
buf[3] = 0x00;
HAL_I2C_Master_Transmit(&hi2c1, Kompass_ADDR, buf, 4, 100);
/*//////////////////////Start of IT Routine//////////////////*/
buf[0] = 0x03;
HAL_I2C_Master_Transmit_IT(&hi2c1, Kompass_ADDR, buf, 1);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1) {
/*/////////////////////printing the value////////////////////////*/
sprintf((char*) Serial_buffer, " X %i \r\n", DataX);
HAL_UART_Transmit(&huart2, (uint8_t*) Serial_buffer, strlen((char*) Serial_buffer), 100);
HAL_Delay(500);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c) {
HAL_I2C_Master_Receive_IT(&hi2c1, Kompass_ADDR, buf, 6);
}
void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c) {
DataX = ((int16_t) buf[0]) << 8 | buf[1];
buf[0] = 0x03;
HAL_I2C_Master_Transmit_IT(&hi2c1, Kompass_ADDR, buf, 1);
}
////////////////////////////I2C Init Function////////////////////////
static void MX_I2C1_Init(void) {
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 100000;
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK) {
Error_Handler();
}
}
After some Error searching I found out, that the error occurs when there I2C port is busy during the reading.
Does somebody have Experience with this I2C Problem?

Multiple write to external eeprom corrupts previous data

I am interfacing AT24C02 external eeprom using stm32f401 nucleo. I am facing few issues.
Lets consider some address
/* 24c02 Device Address */
#define EEPROM_ADDRESS (uint8_t)0xA0
/*Demo addr*/
#define DEMO_BYTE_ADDR (uint16_t)0x01
#define DEMO_WORD_ADDR (uint16_t)0x02
#define DEMO_FLOAT_ADDR (uint16_t)0x06
#define DEMO_STRING_ADDR (uint16_t)0x0A
1. Writing and reading simultaneously.
I am able to write and read data to and from eeprom simultaneously.
/*Writing Byte*/
uint8_t byte;
eep_write_byte(DEMO_BYTE_ADDR, 50);
eep_read_byte(DEMO_BYTE_ADDR, &byte);
/*Wrinting word*/
uint32_t word;
eep_write_word(DEMO_WORD_ADDR, 123456789);
word = eep_read_word(DEMO_WORD_ADDR);
/*Writing float*/
float fData;
eep_write_float(DEMO_FLOAT_ADDR, 9876.54);
fData = eep_read_float(DEMO_FLOAT_ADDR);
This code works fine. Below is the snapshot of output.
2. Problems with writing string
After the above portion of code i have written some lines to write string and read string. As you can see in output buffer dest contains some value.
uint8_t dest[50] = {0};
eep_write_string(DEMO_STRING_ADDR, (uint8_t*)"Hello World!", strlen("Hello World!"));
eep_read_string(DEMO_STRING_ADDR, dest, strlen("Hello World!"));
3. After writing all these values the reading shows corrupted data
After the above portion of the code if i read back all the addresses i have wrote gives me corrupted data.
eep_read_byte(DEMO_BYTE_ADDR, &byte);
word = eep_read_word(DEMO_WORD_ADDR);
fData = eep_read_float(DEMO_FLOAT_ADDR);
eep_read_string(DEMO_STRING_ADDR, dest, strlen("Hello World!"));
Below is the snapshot of out for this code.
As you can see all the data is now corrupted.
you can find eeprom.c from this link https://pastebin.com/2vYWYhnw or just scroll below.
/*
* eeprom.c
*
* Created on: 04-Jan-2021
* Author: DEVJEET MANDAL
*/
#include "i2c.h"
#include "eeprom.h"
#include "stdio.h"
#include "stdlib.h"
/* Low Level function */
void eep_small_delay(void) {
for (uint32_t i = 0; i < 65535; i++)
__asm__("NOP");
}
void i2c_error(void) {
HAL_I2C_DeInit(&hi2c1); //De-init i2c bus
__asm__("NOP");
HAL_I2C_Init(&hi2c1); //re-init i2c bus
__asm__("NOP");
}
eep_status_t i2c_write(uint16_t u8_reg_addr, uint8_t *u8_data, uint16_t len) {
HAL_StatusTypeDef xStatus = HAL_ERROR;
xStatus = HAL_I2C_Mem_Write(&hi2c1, EEPROM_ADDRESS, u8_reg_addr, I2C_MEMADD_SIZE_16BIT, u8_data, len, 100);
HAL_Delay(5);
if (xStatus != HAL_OK) {i2c_error();}
return xStatus;
}
eep_status_t i2c_read(uint16_t u8_reg_addr, uint8_t *u8_data, uint16_t len) {
HAL_StatusTypeDef xStatus = HAL_ERROR;
xStatus = HAL_I2C_Mem_Read(&hi2c1, EEPROM_ADDRESS, u8_reg_addr, I2C_MEMADD_SIZE_16BIT, u8_data, len, 100);
eep_small_delay();
if (xStatus != HAL_OK) {i2c_error();}
return xStatus;
}
/* High Level Functions */
eep_status_t eep_write_byte(uint16_t u8_reg_addr, uint8_t u8_data) {
return i2c_write(u8_reg_addr, &u8_data, 1);
}
eep_status_t eep_read_byte(uint16_t u8_reg_addr, uint8_t *u8_data) {
return i2c_read(u8_reg_addr, u8_data, 1);
}
eep_status_t eep_is_data_avaiable(void) {
eep_status_t xStatus = EEP_ERROR;
uint8_t data = 0;
eep_read_byte(EEPROM_DATA_AVAILABLE_ADDR, &data);
if (data == 0) {xStatus = EEP_ERROR;}
else if (data == 1) {xStatus = EEP_OK;}
else {xStatus = EEP_ERROR;}
return xStatus;
}
eep_status_t eep_set_data_available(uint8_t val) {
return eep_write_byte(EEPROM_DATA_AVAILABLE_ADDR, val);
}
eep_status_t eep_write_word(uint16_t reg_addr, uint32_t value) {
uint8_t val_byte[4] = {0};
val_byte[0] = (value >> 24) & 0xFF;
val_byte[1] = (value >> 16) & 0xFF;
val_byte[2] = (value >> 8) & 0xFF;
val_byte[3] = (value >> 0) & 0xFF;
return i2c_write(reg_addr, val_byte, 4);
}
eep_status_t eep_write_float(uint16_t reg_addr, float value) {
union FtoHex{
float fval;
uint32_t hval;
}float_to_hex;
float_to_hex.fval = value;
return eep_write_word(reg_addr, float_to_hex.hval);
}
uint32_t eep_read_word(uint16_t reg_addr) {
uint8_t val_buff[4] = {0};
i2c_read(reg_addr, val_buff, 4);
return ((val_buff[0] << 24) | (val_buff[1] << 16) | (val_buff[2] << 8) | (val_buff[3] << 0));
}
float eep_read_float(uint8_t reg_addr) {
union FtoHex{
float fval;
uint32_t hval;
}float_to_hex;
float_to_hex.hval = eep_read_word(reg_addr);
return float_to_hex.fval;
}
void eep_write_string(uint16_t reg_addr, uint8_t *src, uint16_t len) {
i2c_write(reg_addr, src, len);
}
void eep_read_string(uint16_t reg_addr, uint8_t *dest, uint16_t len) {
i2c_read(reg_addr, dest, len);
}
//---------------------------------------------------------------------
Almost forgot to mention i m running I2C #400Khz. Though i have tried 100KHz which results same.
Below is the HAL generated I2C init.
/* I2C1 init function */
void MX_I2C1_Init(void)
{
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 400000;
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
{
Error_Handler();
}
}
Now the question is why this problem. Basically the HAL should take care of all the situation and i will just send data to it. Any help will be appreciated.
Regards.
You missed that AT24C02 is organized in 16 byte (write) pages.
The corruption is caused by rollover/wrap # offset 0x0F when writing the string starting # offset 0x0A.
See the data sheet for details.

STM32 F3 Discovery ADC with DMA and Nvic

I have to use 4 ADC channels in my stm32f3 Discovery, so I've decided to use DMA with Nvic. Values sent by USART are correct, however, the DMA1 Channel1 interrupt is called only once after downloading code to flash. I need a continuous conversion, is there something wrong with ADC/DMA/Nvic configuration?
#include"stm32f30x.h"
#include"stm32f30x_gpio.h"
#include"stm32f30x_rcc.h"
#include"stm32f30x_usart.h"
#include"stm32f30x_misc.h"
#include"stm32f30x_adc.h"
#include"stm32f30x_tim.h"
#include"stm32f30x_dma.h"
#define ADC1_DR ((uint32_t)0x4001244C)
__IO uint16_t calibration_value = 0;
__IO uint32_t TimingDelay = 0;
__IO uint16_t ADC_Values[4];
uint16_t tmp[4];
volatile uint32_t dmaFlag = 0;
volatile char rxData[100];
volatile long int rxIndex=0, rxFlag=0;
void USART_puts( USART_TypeDef* USARTx, char *str )
{
while(*str)
{
while( USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET );
USART_SendData(USARTx, *str);
*str++;
}
}
void adc_init(void);
int main(void)
{
int8_t dmaIndex;
int k;
usart_init();
USART_puts(USART1,"ok");
adc_init();
while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_RDY));
DMA_Cmd(DMA1_Channel1, ENABLE);
ADC_StartConversion(ADC1);
//
while(1)
{
while(!dmaFlag);
usart_num(tmp[0]);
usart_num(tmp[1]);
usart_num(tmp[2]);
usart_num(tmp[3]);
for(k=0;k<10000000;k++);
dmaFlag= 0;
}
}
void adc_init(void)
{
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure1;
GPIO_InitStructure1.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
GPIO_InitStructure1.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure1.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOC, &GPIO_InitStructure1);
RCC_ADCCLKConfig(RCC_ADC12PLLCLK_Div2);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ADC12, ENABLE);
ADC_CommonInitTypeDef ADC_CommonInitStructure;
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Clock = ADC_Clock_AsynClkMode;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInitStructure.ADC_DMAMode = ADC_DMAMode_Circular;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = 0;
ADC_CommonInit(ADC1, &ADC_CommonInitStructure);
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_ContinuousConvMode = ADC_ContinuousConvMode_Enable;
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ExternalTrigConvEvent = ADC_ExternalTrigConvEvent_0;
ADC_InitStructure.ADC_ExternalTrigEventEdge = ADC_ExternalTrigEventEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_OverrunMode = ADC_OverrunMode_Disable;
ADC_InitStructure.ADC_AutoInjMode = ADC_AutoInjec_Disable;
ADC_InitStructure.ADC_NbrOfRegChannel = 4;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_StructInit(&ADC_InitStructure);
ADC_VoltageRegulatorCmd(ADC1, ENABLE);
ADC_SelectCalibrationMode(ADC1, ADC_CalibrationMode_Single);
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1) != RESET );
calibration_value = ADC_GetCalibrationValue(ADC1);
ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 1, ADC_SampleTime_7Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 2, ADC_SampleTime_7Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 3, ADC_SampleTime_7Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_9, 4, ADC_SampleTime_7Cycles5);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
DMA_InitTypeDef DMA_InitStructure;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC_Values;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = 4;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // 16 bit
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; // 16 bit
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
DMA_Cmd(DMA1_Channel1, ENABLE);
ADC_DMACmd(ADC1, ENABLE);
ADC_Cmd(ADC1, ENABLE);
}
void DMA1_Channel1_IRQHandler(void)
{
USART_puts(USART1,"fsfr");
if (DMA_GetITStatus(DMA1_IT_TC1))
{
int dmaIndex;
for(dmaIndex=0; dmaIndex<4; dmaIndex++)
{
tmp[dmaIndex]=ADC_Values[dmaIndex]/4;
}
DMA_ClearITPendingBit(DMA1_IT_TC1);
dmaFlag= 1;
}
}
void usart_init( void )
{
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init( GPIOA, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_7);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_7);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
USART_ITConfig( USART1, USART_IT_RXNE, ENABLE);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_Init(&NVIC_InitStructure);
USART_Cmd( USART1, ENABLE);
}
void USART1_IRQHandler( void )
{
if( USART_GetITStatus( USART1, USART_IT_RXNE) )
{
rxData[rxIndex] = USART_ReceiveData(USART1);
// USART_ClearITPendingBit(USART1,USART_IT_RXNE);
while( !(rxData[rxIndex] == 'e') )
{
if( USART_GetITStatus( USART1, USART_IT_RXNE) )
{
rxIndex++;
rxData[rxIndex] = USART_ReceiveData(USART1);
if( rxData[rxIndex] == ' ')
rxData[rxIndex] = '0';
USART_ClearITPendingBit(USART1,USART_IT_RXNE);
}
}
rxFlag = 1;
}
///USART_ClearITPendingBit(USART1,USART_IT_RXNE);
}
void rxDataClear( void )
{
int i=0;
while( rxData[i] )
{
rxData[i] = 0;
i++;
}
rxIndex = 0;
}
void usart_float( float liczba )
{
float tmp;
char dane[7];
tmp = liczba;
dane[0]=(((int)tmp %1000) /100)+0x30;
dane[1]=(((int)tmp %100) /10)+0x30;
dane[2]=(((int)tmp %10))+0x30;
dane[3]='.';
dane[4]=((int)(tmp*10) %10)+0x30;
dane[5]=((int)(tmp*100) %10)+0x30;
dane[6]=((int)(tmp*1000) %10)+0x30;
dane[7]='\0';
USART_puts(USART1,dane);
}
void usart_num(signed int liczba)
{
int i, length=0,znak=0;
char liczba_str[10] = {0};
if( liczba < 0 )
{
znak = 1;
liczba = - liczba;
}
for( i = 1; (i <= liczba) && (length <= 10); i*=10 )
{
if( (liczba/i) > 0 )
length++;
}
if(length == 0)
length = 1;
i = 1;
while(length)
{
liczba_str[length-1]=liczba%(10*i)/i+48;
length--;
i*= 10;
}
if(znak)
USART_puts(USART1,"-");
else
USART_puts(USART1," ");
USART_puts(USART1, liczba_str );
}
Try this to continuous conversion,change this:
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
to :
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
and replace this:
DMA_Cmd(DMA1_Channel1, ENABLE);
ADC_DMACmd(ADC1, ENABLE);
ADC_Cmd(ADC1, ENABLE);
by:
ADC_DMAConfig( ADC1, ADC_DMAMode_Circular );
/* Enable ADC1 DMA */
ADC_DMACmd( ADC1, ENABLE );
/* Enable ADC1 */
ADC_Cmd( ADC1, ENABLE );
/* Wait for ADC1 ready */
i = 0xFFFFF;
while(!ADC_GetFlagStatus( ADC1, ADC_FLAG_RDY ) && i) i--;
/* Enable the DMA1 channel1 */
DMA_Cmd( DMA1_Channel1, ENABLE );
/* Start ADC1 Software Conversion */
ADC_StartConversion( ADC1);`