CRC16 is right at the first function call but is wrong on the next function call? - i2c

Declaration variables:
uint8_t NDEFSelect[15] = {0x02,0x00,0xA4,0x04,0x00,0x07,0xD2,0x76,0x00,0x00,0x85,0x01,0x01,0x00,0x35,0xC0};
uint8_t selectCCFile[9] = {0x03,0x00,0xA4,0x00,0x0C,0x02,0xE1,0x03,0xD2,0xAF};
Function CRC16:
uint16_t M24SR_UpdateCrc (uint8_t ch, uint16_t *lpwCrc)
{
ch = (ch^(uint8_t)((*lpwCrc) & 0x00FF));
ch = (ch^(ch<<4));
*lpwCrc = (*lpwCrc >> 8)^((uint16_t)ch << 8)^((uint16_t)ch<<3)^((uint16_t)ch>>4);
return(*lpwCrc);
}
/**
* #brief This function returns the CRC 16
* #param Data : pointer on the data used to compute the CRC16
* #param Length : number of byte of the data
* #retval CRC16
*/
uint16_t M24SR_ComputeCrc(uint8_t *Data, uint8_t Length, uint8_t *crc0, uint8_t *crc1)
{
uint8_t chBlock = 0;
uint16_t wCrc = 0;
wCrc = 0x6363; // ITU-V.41
do {
chBlock = *Data++;
M24SR_UpdateCrc(chBlock, &wCrc);
} while (--Length);
*crc0 = (uint8_t) (wCrc & 0xFF);
*crc1 = (uint8_t) ((wCrc >> 8) & 0xFF);
return wCrc ;
}
Function call main loop:
M24SR_ComputeCrc(NDEFSelect, sizeof(NDEFSelect)-1, &(NDEFSelect[14]), &(NDEFSelect[15]));
M24SR_ComputeCrc(selectCCFile, sizeof(selectCCFile)-1, &(selectCCFile[8]), &(selectCCFile[9]));
I think the variables values still remember last function call. How do I reset this variables?

Related

Using STM32 FMC HAL driver with parallel DAC

Im trying to generate sinusoidal signal with STM32f767 and DAC8412. DAC have 12 bit data bus and 2 bit address to select one of the four analog outputs. I've configuried FMC in CubeIDE for a SRAM memory with 16 bit data and 2 bit addres. I was able to create buffer with 4096 integer values of sin(). Then i've tried to write them to addres 0x60000000, but it only writes 4 values. After that, program goes to HardFault_Handler().
#define SRAM_BANK_ADDR ((uint32_t)0x60000000)
#define RESOLUTION_T ((uint32_t)0x1000)
#define RESOLUTION_Y ((uint32_t)0x1000)
uint32_t aTxBuffer[RESOLUTION_T];
uint32_t address = SRAM_BANK_ADDR;
Thats how i try to send data to DAC:
for (uint32_t i = 0; i<RESOLUTION_T; i++ )
{
*(__IO uint32_t*) address = aTxBuffer[i];
}
Thats how i fill buffer:
static void Fill_Buffer(uint32_t *pBuffer, uint32_t res_T, uint32_t res_Y)
{
uint32_t tmpIndex = 0;
double sinVal;
/* Put in global buffer different values */
for (tmpIndex = 0; tmpIndex < res_T; tmpIndex++ )
{
sinVal = round((sin(M_TWOPI*tmpIndex/res_T)+1)*res_Y/2);
pBuffer[tmpIndex] = sinVal;
}
}

Why is the voltage collected by stm32adc inaccurate?

I am using the STM32F103C8T6. I use the ADC for multi-channel voltage acquisition, and a potentiometer to control the voltage change. I find that the ADC value changes fluctuate. Why?
This is part of my ADC code:
uint32_t ADC_Get_Average(uint8_t ch,uint8_t times)
{
ADC_ChannelConfTypeDef sConfig;
uint32_t value_sum=0;
uint8_t i;
switch(ch)
{
case 1:sConfig.Channel = ADC_CHANNEL_1;break;
case 2:sConfig.Channel = ADC_CHANNEL_2;break;
case 3:sConfig.Channel = ADC_CHANNEL_3;break;
}
sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
sConfig.Rank = 1;
HAL_ADC_ConfigChannel(&hadc1,&sConfig);
for(i=0;i<times;i++)
{
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1,5);
value_sum += HAL_ADC_GetValue(&hadc1);
HAL_ADC_Stop(&hadc1);
}
return value_sum/times;
}
void ADC_PROC(void)
{
ADC_value1 = ADC_Get_Average(1,5) / 4096.0 * 3.3;
ADC_value2 = ADC_Get_Average(2,5) / 4096.0 * 3.3;
ADC_value3 = ADC_Get_Average(3,5) / 4096.0 * 3.3;
sprintf(adcbuff1, "V1:%.2fV", ADC_value1);
oled_show_string(24, 0, adcbuff1, 2);
sprintf(adcbuff2, "V2:%.2fV", ADC_value2);
oled_show_string(24, 2, adcbuff2, 2);
sprintf(adcbuff3, "V3:%.2fV", ADC_value3);
oled_show_string(24, 4, adcbuff3, 2);
}
enter image description here
I have tried to change the length of ADC's acquisition cycle side, but the effect is still the same, with severe fluctuations.

MCP79411 RTC connection via i2c/TWI interface on Atmel SAMG55

I've made a project based on ATSAMG55J19 MCU, programmed with Atmel Studio and ASF 3
Now i'm trying to add an external RTC clock, because internal SAMg55 rtc does not have a backup battery.
The module will be used to read current time after power failure, then i'll use internal RTC, so i need only basic communication. No need to write specific data in EEPROM or setting alarms.
I have a MCP79411, connected via i2c, but there aren't any library suitable for this MCU that uses ASF TWI library.
There are many Arduino implementation, but they uses Wire.h library, and i can't port it.
I made an attempt porting this simple "driver": https://www.ccsinfo.com/forum/viewtopic.php?t=54105
Here is some code
static void i2c_start(void){
static twi_options_t ext3_twi_options;
flexcom_enable(FLEXCOM4);
flexcom_set_opmode(FLEXCOM4, FLEXCOM_TWI);
ext3_twi_options.master_clk = sysclk_get_cpu_hz();
ext3_twi_options.speed = 100000;
ext3_twi_options.smbus = 0;
twi_master_init(TWI4, &ext3_twi_options);
}
// Init Real Time Clock
void rtc_Init(void)
{
uint8_t seconds = 0;
i2c_start();
twi_write_byte(TWI4, ADDR_RTCC_WRITE); // WR to RTC
twi_write_byte(TWI4, ADDR_SEC); // REG 0
twi_write_byte(TWI4, ADDR_RTCC_READ); // RD from RTC
seconds = bcd2bin(i2c_read(0)); // Read current "seconds" in rtc
//i2c_stop();
//seconds &= 0x7F;
seconds |= 0x80; //set to 1 bit 7 of seconds(ST) enabling oscillator
delay_us(3);
twi_write_byte(TWI4, ADDR_RTCC_WRITE); // WR to RTC
twi_write_byte(TWI4, ADDR_SEC); // REG 0
twi_write_byte(TWI4, bin2bcd(seconds) | 0x80); // Start oscillator with current "seconds value
twi_write_byte(TWI4, ADDR_RTCC_WRITE); // WR to RTC
twi_write_byte(TWI4, 0x07); // Control Register
twi_write_byte(TWI4, 0x80); // Disable squarewave output pin
//i2c_stop();
}
Then i tried rtc_set_date_time(uint8_t day, uint8_t mth, uint8_t year, uint8_t dow, uint8_t hr, uint8_t min, uint8_t sec)
and
void rtc_get_time(uint8_t &hr, uint8_t &min, uint8_t &sec)
{
twi_write_byte(TWI4, ADDR_RTCC_WRITE);
twi_write_byte(TWI4, 0x00);
twi_write_byte(TWI4, ADDR_RTCC_READ);
sec = bcd2bin(twi_read_byte(TWI4) & 0x7f); //0x7f b01111111
min = bcd2bin(twi_read_byte(TWI4) & 0x7f); //0x7f
hr = bcd2bin(twi_read_byte(TWI4) & 0x3f); //0x3f b00111111
//i2c_stop();
}
But i always get "0" bytes.
i could not understand the correct way to open communication and read bytes from i2c.
The only reference i found is http://asf.atmel.com/docs/latest/sam.drivers.twi.twi_eeprom_example.samg53_xplained_pro/html/index.html but it seems to be a very different type of communication.
What is the correct way to send and receive that bytes via i2c?
I managed to get and set data. I post a draft of library:
#include "asf.h"
#include "conf_board_3in4out.h"
#include "external_rtc.h"
#include <time.h>
//#include <time_utils.h>
twi_packet_t packet_tx, packet_rx;
// helper functions to manipulate BCD and binary to integers
static int bcd2dec(char r_char)
{
MSN = (r_char & 0xF0)/16;
LSN = r_char & 0x0F;
return(10*MSN + LSN);
}
static char msn(char tim)
{
return (tim & 0xF0)/16;
}
static char lsn(char tim)
{
return (tim & 0x0F);
}
#define RTC_ADDR 0x6F // 7 bits
char config_t[10];
char config_2[8];
char tim_read[8];
#define ADDR_SEC 0x00 // address of SECONDS register
#define ADDR_MIN 0x01 // address of MINUTES register
#define ADDR_HOUR 0x02 // address of HOURS register
#define ADDR_DAY 0x03 // address of DAY OF WEEK register
#define ADDR_STAT 0x03 // address of STATUS register
#define ADDR_DATE 0x04 // address of DATE register
#define ADDR_MNTH 0x05 // address of MONTH register
#define ADDR_YEAR 0x06 // address of YEAR register
#define ADDR_CTRL 0x07 // address of CONTROL register
#define ADDR_CAL 0x08 // address of CALIB register
#define ADDR_ULID 0x09 // address of UNLOCK ID register
#define ADDR_SAVtoBAT_MIN 0x18 // address of T_SAVER MIN(VDD->BAT)
#define ADDR_SAVtoBAT_HR 0x19 // address of T_SAVER HR (VDD->BAT)
#define ADDR_SAVtoBAT_DAT 0x1a // address of T_SAVER DAT(VDD->BAT)
#define ADDR_SAVtoBAT_MTH 0x1b // address of T_SAVER MTH(VDD->BAT)
#define START_32KHZ 0x80 // start crystal: ST = b7 (ADDR_SEC)
#define OSCON 0x20 // state of the oscillator(running or not)
#define VBATEN 0x08 // enable battery for back-up
static uint8_t bin2bcd(uint8_t binary_value)
{
uint8_t temp;
uint8_t retval;
temp = binary_value;
retval = 0;
if(temp >= 10)
{
temp -= 10;
retval += 0x10;
}
else
{
retval += temp;
//break;
}
return(retval);
}
static uint8_t bcd2bin(uint8_t bcd_value)
{
uint8_t temp;
temp = bcd_value;
temp >>= 1;
temp &= 0x78;
return(temp + (temp >> 2) + (bcd_value & 0x0f));
}
static void setConfig(void){
config_2[0] = tim_read[0] | START_32KHZ; // bitwise OR sets Start osc bit = 1
config_2[1] = tim_read[1];
config_2[2] = tim_read[2];
//0x03h – Contains the BCD day. The range is 1-7.
//Bit 3 is the VBATEN bit. If this bit is set, the
//internal circuitry is connected to the VBAT pin
//when VCC fails. If this bit is ‘0’ then the VBAT pin is
//disconnected and the only current drain on the
//external battery is the VBAT pin leakage.
config_2[3] = tim_read[3] | VBATEN;
config_2[4] = tim_read[4];
config_2[5] = tim_read[5];
config_2[6] = tim_read[6];
config_2[7] = 0x00; // control b3 - extosc = 0
}
static void initialize(void){
uint8_t buf[7]; // Fill this with RTC clock data for all seven registers
// read stored time data
config_t[0] = 0x00; //reset pointer reg to '00'
// Set up config to read the time and set the control bits
//i2c.write(addr, config_t, 1); // write address 00
packet_tx.chip = RTC_ADDR;
packet_tx.addr[0] = 0; // RTCSEC
packet_tx.addr_length = 1;
packet_tx.buffer = config_t;
packet_tx.length = 1;
twi_master_write(TWI4, &packet_tx);
delay_ms(250);
//
//i2c.read(addr, tim_read, 7); //read time ss mm hh from r1, r2, r3
packet_rx.chip = RTC_ADDR;
packet_rx.addr[0] = 0; // RTCSEC
packet_rx.addr_length = 1;
packet_rx.buffer = tim_read;
packet_rx.length = sizeof(tim_read);
twi_master_read(TWI4, &packet_rx);
delay_ms(250);
setConfig(); //puts RTCC data into config array from tim_read array
// write the config data
//i2c.write(addr, config_t, 9); // write the config data back to the RTCC module
packet_tx.chip = RTC_ADDR;
packet_tx.addr[0] = 0; // RTCSEC
packet_tx.addr_length = 1;
packet_tx.buffer = config_2;
packet_tx.length = sizeof(config_2);
twi_master_write(TWI4, &packet_tx);
}
static void write_time(void){
// re-calculate mins
mins = 8; //ORE 10:08
mins = mins%60;
ch_mins = 16*(mins/10) + mins%10;
MSN = msn(ch_mins);
LSN = lsn(ch_mins);
tim_read[1] = ch_mins;
inc_mins = 0;
//write the data back to RTCC
setConfig();
//i2c.write(addr, config_t, 9);
/* Configure the data packet to be transmitted */
packet_tx.chip = RTC_ADDR;
packet_tx.addr[0] = 0; // RTCSEC
packet_tx.addr_length = 1;
packet_tx.buffer = config_2;
packet_tx.length = sizeof(config_2);
twi_master_write(TWI4, &packet_tx);
//Display and set hours
//hrs = bcd2dec(tim_read[2]);
// re-calculate hrs
hrs = 10; //ORE 10:08
hrs = hrs%24;
ch_hrs = 16*(hrs/10) + hrs%10;
MSN = msn(ch_hrs);
LSN = lsn(ch_hrs);
tim_read[2] = ch_hrs;
inc_hr = 0;
//write the data back to RTCC
setConfig();
/* Configure the data packet to be transmitted */
packet_tx.chip = RTC_ADDR;
packet_tx.addr[0] = 0; // RTCSEC
packet_tx.addr_length = 1;
packet_tx.buffer = config_2;
packet_tx.length = sizeof(config_2);
twi_master_write(TWI4, &packet_tx);
}
static void read_time(void){
//config_t[0] = 0x00; //reset pointer reg to '00'
//// First Get the time
////i2c.write(addr, config_t, 1); // write address 00
//packet_tx.chip = RTC_ADDR;
//packet_tx.addr[0] = 0; // RTCSEC
//packet_tx.addr_length = 1;
//packet_tx.buffer = config_t;
//packet_tx.length = 1;
//
//twi_master_write(TWI4, &packet_tx);
delay_ms(250);
uint8_t buf[7]; // Fill this with RTC clock data for all seven registers
/* Configure the data packet to be received */
packet_rx.chip = RTC_ADDR;
packet_rx.addr[0] = 0; // RTCSEC
packet_rx.addr_length = 1;
packet_rx.buffer = buf;
packet_rx.length = sizeof(buf);
twi_master_read(TWI4, &packet_rx);
for(uint8_t i = 0; i < sizeof(buf); i++){
tim_read[i] = buf[i];
}
}
void example_print_time(void){
//initialize();
delay_ms(1000);
//write_time(); //commented to see if time is permanent
delay_ms(1000);
read_time();
while(1){
printf("Reading time\n");
printf("%d:%d:%d\n", bcd2dec(tim_read[2]), bcd2dec(tim_read[1]), bcd2dec(tim_read[0] ^ START_32KHZ));
delay_ms(1000);
read_time();
}
}

How to read data from MPU6050 using STM32F4

I need to monitorate the acelleration of a object. I'm using the MPU6050(accelerometer and gyroscope) and the controller STM32F401RBT6. The code below is the solution that i'm using for this.
#define MPU6050_ADDR 0xD0
#define SMPLRT_DIV_REG 0x19
#define GYRO_CONFIG_REG 0x1B
#define ACCEL_CONFIG_REG 0x1C
#define ACCEL_XOUT_H_REG 0x3B
#define TEMP_OUT_H_REG 0x41
#define GYRO_XOUT_H_REG 0x43
#define PWR_MGMT_1_REG 0x6B
#define WHO_AM_I_REG 0X75
uint16_t Accel_X_RAW,Accel_Y_RAW,Accel_Z_RAW;
uint16_t Ax,Ay,Az;
char buffer[10];
void MPU6050_Init(void)
{
uint8_t check, data;
HAL_I2C_Mem_Read(&hi2c3,MPU6050_ADDR,WHO_AM_I_REG,1,&check,1,100);
if(check == 104)
{
data = 0x07;
HAL_I2C_Mem_Write(&hi2c3,MPU6050_ADDR,SMPLRT_DIV_REG,1,&data,1,50);
HAL_Delay(50);
data = 0x00;
HAL_I2C_Mem_Write(&hi2c3,MPU6050_ADDR,ACCEL_CONFIG_REG,1,&data,1,50);
HAL_Delay(50);
data = 0x00;
HAL_I2C_Mem_Write(&hi2c3,MPU6050_ADDR,GYRO_CONFIG_REG,1,&data,1,50);
HAL_Delay(50);
data = 0;
HAL_I2C_Mem_Write(&hi2c3,MPU6050_ADDR,PWR_MGMT_1_REG,1,&data,1,50);
HAL_Delay(50);
}
}
void MPU6050_Read_Accel(void)
{
uint8_t recData[6];
for(int i=0;i<6;i++) recData[i] = 0;
HAL_I2C_Mem_Read(&hi2c3,MPU6050_ADDR,ACCEL_XOUT_H_REG,I2C_MEMADD_SIZE_8BIT,recData,6,100);
HAL_Delay(50);
uint16_t dataConvert1,dataConvert2;
dataConvert1 = (uint16_t)(0x0000 | recData[0]) << 8;
dataConvert2 = (uint16_t)(0x0000 | recData[1]);
Accel_X_RAW = dataConvert1 | dataConvert2;
dataConvert1 = (uint16_t)(0x0000 | recData[2]) << 8;
dataConvert2 = (uint16_t)(0x0000 | recData[3]);
Accel_Y_RAW = dataConvert1 | dataConvert2;
dataConvert1 = (uint16_t)(0x0000 | recData[4]) << 8;
dataConvert2 = (uint16_t)(0x0000 | recData[5]);
Accel_Z_RAW = dataConvert1 | dataConvert2;
Ax = (uint16_t)(Accel_X_RAW / 16384);
Ay = (uint16_t)(Accel_Y_RAW / 16384);
Az = (uint16_t)(Accel_Z_RAW / 16384);
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_I2C3_Init();
MX_GPIO_Init();
MX_USB_DEVICE_Init();
MPU6050_Init();
while (1)
{
MPU6050_Read_Accel();
sprintf(buffer, "%d / ", Accel_X_RAW);
CDC_Transmit_FS((char*)buffer,10);
}
}
I already did it on ATMEL Controler (Arduino) and it worked, but not on STM32.
I am trying to read the value of X Axis and show it using the USB CDC. This code sets a value for the `` `Accel_X_RAW```` variable between 0 and 65535. In Arduino, the reference value was 32768 when the object was stopped, but reading with STM32 remains at the maximum value (65535) if don't have movement. I don't know what's wrong with this code, I tried many options, but it still doesn't work. Can you help me please.
According to the MPU6050 datasheet, the 16-bit values for acceleration and gyroscope are returned in the signed 2's complement form (it detects acceleration values in the range +-g). As you are receiving signed data in the unsigned variables, the result is not what you expect. Therefore, replace all uint16_t datatypes with int16_t.
The reason why you are getting 65535 value; the hex value of -1 in signed int16_t form is 0xFFFF. However, if you store it in the uint16_t variable, it will be read as 65535. I am assuming that the default acceleration value at rest is -1g.
#include <stdlib.h> /* For using memset */
#define MPU6050_ADDR 0xD0
#define SMPLRT_DIV_REG 0x19
#define GYRO_CONFIG_REG 0x1B
#define ACCEL_CONFIG_REG 0x1C
#define ACCEL_XOUT_H_REG 0x3B
#define TEMP_OUT_H_REG 0x41
#define GYRO_XOUT_H_REG 0x43
#define PWR_MGMT_1_REG 0x6B
#define WHO_AM_I_REG 0X75
int16_t Accel_X_RAW,Accel_Y_RAW,Accel_Z_RAW;
int16_t Ax,Ay,Az;
char buffer[10];
void MPU6050_Init(void)
{
uint8_t check, data;
HAL_I2C_Mem_Read(&hi2c3,MPU6050_ADDR,WHO_AM_I_REG,1,&check,1,100);
if(check == 104)
{
data = 0x07;
HAL_I2C_Mem_Write(&hi2c3,MPU6050_ADDR,SMPLRT_DIV_REG,1,&data,1,50);
HAL_Delay(50);
data = 0x00;
HAL_I2C_Mem_Write(&hi2c3,MPU6050_ADDR,ACCEL_CONFIG_REG,1,&data,1,50);
HAL_Delay(50);
data = 0x00;
HAL_I2C_Mem_Write(&hi2c3,MPU6050_ADDR,GYRO_CONFIG_REG,1,&data,1,50);
HAL_Delay(50);
data = 0;
HAL_I2C_Mem_Write(&hi2c3,MPU6050_ADDR,PWR_MGMT_1_REG,1,&data,1,50);
HAL_Delay(50);
}
}
void MPU6050_Read_Accel(void)
{
uint8_t recData[6];
//for(int i=0;i<6;i++) recData[i] = 0;
memset(recData, 0, sizeof(recData));
HAL_I2C_Mem_Read(&hi2c3,MPU6050_ADDR,ACCEL_XOUT_H_REG,I2C_MEMADD_SIZE_8BIT,recData,6,100);
HAL_Delay(50);
Accel_X_RAW = (int16_t)(recData[0] << 8 | recData[1]);
Accel_Y_RAW = (int16_t)(recData[2] << 8 | recData[3]);
Accel_Z_RAW = (int16_t)(recData[4] << 8 | recData[5]);
Ax = (int16_t)(Accel_X_RAW / 16384);
Ay = (int16_t)(Accel_Y_RAW / 16384);
Az = (int16_t)(Accel_Z_RAW / 16384);
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_I2C3_Init();
MX_GPIO_Init();
MX_USB_DEVICE_Init();
MPU6050_Init();
while (1)
{
MPU6050_Read_Accel();
sprintf(buffer, "%d / ", Accel_X_RAW);
CDC_Transmit_FS((char*)buffer,10);
}
}

ffmpeg +libx264 iPhone -> 'avcodec_encode_video' return always 0 . please advice

av_register_all();
AVCodec *codec;
AVCodecContext *c= NULL;
int out_size, size, outbuf_size;
//FILE *f;
uint8_t *outbuf;
printf("Video encoding\n");
/* find the mpeg video encoder */
codec =avcodec_find_encoder(CODEC_ID_H264);//avcodec_find_encoder_by_name("libx264"); //avcodec_find_encoder(CODEC_ID_H264);//CODEC_ID_H264);
NSLog(#"codec = %i",codec);
if (!codec) {
fprintf(stderr, "codec not found\n");
exit(1);
}
c= avcodec_alloc_context();
/* put sample parameters */
c->bit_rate = 400000;
c->bit_rate_tolerance = 10;
c->me_method = 2;
/* resolution must be a multiple of two */
c->width = 352;//width;//352;
c->height = 288;//height;//288;
/* frames per second */
c->time_base= (AVRational){1,25};
c->gop_size = 10; /* emit one intra frame every ten frames */
//c->max_b_frames=1;
c->pix_fmt = PIX_FMT_YUV420P;
c ->me_range = 16;
c ->max_qdiff = 4;
c ->qmin = 10;
c ->qmax = 51;
c ->qcompress = 0.6f;
'avcodec_encode_video' is always 0 .
I guess that because 'non-strictly-monotonic PTS' warning, do you konw same situation?
For me also it returns 0 always. But encodes fine. I dont think there is an issue if it returns 0. In the avcodec.h, you can see this
"On error a negative value is returned, on success zero or the number
* of bytes used from the output buffer."