stm32f4 fatfs f_write whitemarks - stm32

Im struggling with fatfs on stm32f4. With no problem i can mount, create file and write on it by : char my_data[]="hello world" and in windows file shows normally but when i try use code as loger :
float bmp180Pressure=1000.1;
char presur_1[6];//bufor znakow do konwersji
sprintf(presur_1,"%0.1f",bmp180Pressure);
char new_line[]="\n\r";
if(f_mount(&myFat, SDPath, 1)== FR_OK)
{
f_open(&myFile, "dane.txt", FA_READ|FA_WRITE);
f_lseek(&myFile, f_size(&myFile));//sets end of data
f_write(&myFile, presur_1, 6, &byteCount);
f_write(&myFile, new_line,4, &byteCount);
f_close(&myFile);
HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_15);
}
When i was read from computer i have :top : notepad ++ buttom :windows notepad

There are at least two problems in your code:
The string for the number is too short. C strings are terminated with a null byte. So presur_1 needs to be at least 7 bytes long (6 for the number and 1 for the null byte). Since it's only 6 bytes long, sprintf will write beyond the allocated length and destroy some other data.
The string for the newline is initialized with a string of 2 characters (plus the null byte). However, you write 4 characters to the file. So in addition to the newline, a NUL character and a garbage byte will end up in the file.
The fixed code looks like this:
float bmp180Pressure = 1000.1;
char presur_1[20];//bufor znakow do konwersji
int presur_1_len = sprintf(presur_1,"%0.1f\n\r",bmp180Pressure);
if(f_mount(&myFat, SDPath, 1)== FR_OK)
{
f_open(&myFile, "dane.txt", FA_READ|FA_WRITE);
f_lseek(&myFile, f_size(&myFile));//sets end of data
f_write(&myFile, presur_1, presur_1_len, &byteCount);
f_close(&myFile);
HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_15);
}

Related

STM32 SPI data is sent the reverse way

I've been experimenting with writing to an external EEPROM using SPI and I've had mixed success. The data does get shifted out but in an opposite manner. The EEPROM requires a start bit and then an opcode which is essentially a 2-bit code for read, write and erase. Essentially the start bit and the opcode are combined into one byte. I'm creating a 32-bit unsigned int and then bit-shifting the values into it. When I transmit these I see that the actual data is being seen first and then the SB+opcode and then the memory address. How do I reverse this to see the opcode first then the memory address and then the actual data. As seen in the image below, the data is BCDE, SB+opcode is 07 and the memory address is 3F. The correct sequence should be 07, 3F and then BCDE (I think!).
Here is the code:
uint8_t mem_addr = 0x3F;
uint16_t data = 0xBCDE;
uint32_t write_package = (ERASE << 24 | mem_addr << 16 | data);
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_SPI_Transmit(&hspi1, &write_package, 2, HAL_MAX_DELAY);
HAL_Delay(10);
}
/* USER CODE END 3 */
It looks like as your SPI interface is set up to process 16 bit halfwords at a time. Therefore it would make sense to break up the data to be sent into 16 bit halfwords too. That would take care of the ordering.
uint8_t mem_addr = 0x3F;
uint16_t data = 0xBCDE;
uint16_t write_package[2] = {
(ERASE << 8) | mem_addr,
data
};
HAL_SPI_Transmit(&hspi1, (uint8_t *)write_package, 2, HAL_MAX_DELAY);
EDIT
Added an explicit cast. As noted in the comments, without the explicit cast it wouldn't compile as C++ code, and cause some warnings as C code.
You're packing your information into a 32 bit integer, on line 3 of your code you have the decision about which bits of data are placed where in the word. To change the order you can replace the line with:
uint32_t write_package = ((data << 16) | (mem_addr << 8) | (ERASE));
That is shifting data 16 bits left into the most significant 16 bits of the word, shifting mem_addr up by 8 bits and or-ing it in, and then adding ERASE in the least significant bits.
Your problem is the Endianness.
By default the STM32 uses little edian so the lowest byte of the uint32_t is stored at the first adrress.
If I'm right this is the declaration if the transmit function you are using:
HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)
It requires a pointer to uint8_t as data (and not a uint32_t) so you should get at least a warning if you compile your code.
If you want to write code that is independent of the used endianess, you should store your data into an array instead of one "big" variable.
uint8_t write_package[4];
write_package[0] = ERASE;
write_package[1] = mem_addr;
write_package[2] = (data >> 8) & 0xFF;
write_package[3] = (data & 0xFF);

How do I get the per-spec output of a LV-MaxSonar LV-EZ0 rangefinder with Android Things?

I'm using this sensor with a Raspberry Pi B 3 and Android Things 1.0
I have it connected as per these instructions
The spec for its output suggests I should receive "an ASCII capital “R”, followed by three ASCII character digits representing the range in inches up to a maximum of 255, followed by a carriage return (ASCII 13)"
I have connected to the device and configured it as follows (connection parameters map to the "Serial, 0 to Vcc, 9600 Baud, 81N" in that spec, I think):
PeripheralManager manager = PeripheralManager.getInstance();
mDevice = manager.openUartDevice(name);
mDevice.setBaudrate(9600);
mDevice.setDataSize(8);
mDevice.setParity(UartDevice.PARITY_NONE);
mDevice.setStopBits(1);
mDevice.registerUartDeviceCallback(mUartCallback);
I am reading from its buffer in that callback as follows:
public void readUartBuffer(UartDevice uart) throws IOException {
// "The output is an ASCII capital “R”, followed by three ASCII character digits
// representing the range in inches up to a maximum of 255, followed by a carriage return
// (ASCII 13)
ByteArrayOutputStream bout = new ByteArrayOutputStream();
final int maxCount = 1024;
byte[] buffer = new byte[maxCount];
int total = 0;
int cycles = 0;
int count;
bout.write(23);
while ((count = uart.read(buffer, buffer.length)) > 0) {
bout.write(buffer, 0, count);
total += count;
cycles++;
}
bout.write(0);
byte[] buf = bout.toByteArray();
String bufStr = Arrays.toString(buf);
Log.d(TAG, "Got " + total + " in " + cycles + ":" + buf.length +"=>" + bufStr);
}
private UartDeviceCallback mUartCallback = new UartDeviceCallback() {
#Override
public boolean onUartDeviceDataAvailable(UartDevice uart) {
// Read available data from the UART device
try {
readUartBuffer(uart);
} catch (IOException e) {
Log.w(TAG, "Unable to access UART device", e);
}
// Continue listening for more interrupts
return true;
}
When I connect the sensor and use this code I get readings back of the form:
05-10 03:59:59.198 1572-1572/org.tomhume.blah D/LVEZ0: Got 7 in 1:9=>[23, 43, 0, 6, -77, -84, 15, 0, 0]
05-10 03:59:59.248 1572-1572/org.tomhume.blah D/LVEZ0: Got 7 in 1:9=>[23, 43, 0, 6, 102, 101, 121, 0, 0]
05-10 03:59:59.298 1572-1572/org.tomhume.blah D/LVEZ0: Got 7 in 1:9=>[23, 43, 0, 6, 102, 99, 121, 0, 0]
The initial 23 and the final 0 on each line are values I have added. Instead of an expected R\d\d\d\13 I expect between them, I'm getting 7 signed bytes. The variance in some of these byte values appears when I move my hand towards and away from the sensor - i.e. the values I'm getting back vary in a way I might expect, even though the output is completely wrong in form and size.
Any ideas what I'm doing wrong here? I suspect it's something extremely obvious, but I'm stumped. Examining the binary values themselves it doesn't look like bits are shifted around by e.g. a mistake in protocol configuration.
I can't test it on a hardware now, but seems algorithm for reading serial data from a LV-MaxSonar LV-EZ0 rangefinder should be slightly different: you should find "an ASCII capital “R” in UART sequence buffer (because LV-EZ0 starts sending data after power on and not synchronized with Raspberry Pi board and first received byte may be not “R” and quantity of received bytes can be less or more then 5 bytes of LV-MaxSonar response^ in one buffer can be several (or part)of LV-MaxSonar responses) and THAN try to parse 3 character digits representing the range in inches and ending CR symbol (if there is no all 3 bytes for digits and CR symbol - than start to find capital “R” again because LV-MaxSonar response is broken (it also can be)). For example take a look at GPS contrib driver especially at processBuffer() of NmeaGpsModule.java and processMessageFrame() of NmeaParser.java - the difference is in your have only one "sentence" and its start is not "GPRMC", but only "R" symbol.
And other important thing: seems there no capital “R” (ASCII 82) in your response buffers - may be some issues in LV-MaxSonar LV-EZ0 connection. Your schematics should be exactly like top right picture on page 6 of datasheet: Independent Sensor Operation: Serial Output Sensor Operation. Also try, for example, to connect LV-MaxSonar LV-EZ0 to USB<->UART (with power output) cable (e.g. like that) and test it in terminal with your PC.

file read using fgetc adds FF at the end

I'm reading a file using fgetc. File reading starts at an offset.At the end I see 8'hFF getting appended at the end of file.I'm expecting 6 bytes in the file but see 7 in them.I'm not sure why this is happening. Any ideas?
Below is my code:
module file_read();
integer fd,fd1,file_char,status;
logic [7:0] captured_data;
initial begin
fd = $fopen("input_file", "rb");
fd1 =$fopen("write_file","w");
status=$fseek(fd,1872,0);
assert (status);
// while ($fgetc(fd) != `EOF) begin
while (!$feof(fd)) begin
file_char=$fgetc(fd);
$display("file char is %h",file_char);
end
end // initial begin
Below are the file contents(in hex):
last line of input_file(total file size =1878):
0000750: 0000 1567 d48d ...g..
write_file:
0000000: 0000 1567 d48d ff ...g...
Thanks!
The reason you are getting the extra 'hff at the end of the written file is due to how $feof (or generally the foef C function) works. Simply put, it doesn't check if the next read is off the end of the file but if the previous read read off the end of the file. So, if you are reading character by character (byte by byte) using $fgetc, $feof will only return true once $fgetc reads off the end of the file, and returns EOF itself (ie, -1 or 'hff if converted to logic [7:0]). You should be checking for this error condition each time you read a byte, something like this:
integer fd, ch;
...
fd = $fopen("file.bin", "rb");
...
while ((ch = $fgetc(fd)) != -1) begin
$display(ch);
end

How to make string input in Assembly language?

Please, does anybody know how to code string input in assembly language? I'm using int 21 to display and input characters.
You can use function 0Ah to read buffered input. Given a string buffer in ds:dx it reads a string of up to length 255. The buffer layout is:
Byte 0 String length (0-255)
Byte 1 Bytes read (0-255, filled by DOS on return)
Bytes 2-..Length+2 (The character string including newline as read by DOS).
An example of a small COM file that reads a string and then echos it back to the user:
org 0x100
start:
push cs
pop ds ; COM file, ds = cs
mov ah, 0x0A ; Function 0Ah Buffered input
mov dx, string_buf ; ds:dx points to string buffer
int 0x21
movzx si, byte [string_buf+1] ; get number of chars read
mov dx, string_buf + 2 ; start of actual string
add si, dx ; si points to string + number of chars read
mov byte [si], '$' ; Terminate string
mov ah, 0x09 ; Function 09h Print character string
int 0x21 ; ds:dx points to string
; Exit
mov ax, 0x4c00
int 0x21
string_buf:
db 255 ; size of buffer in characters
db 0 ; filled by DOS with actual size
times 255 db 0 ; actual string
Note that it will overwrite the input line (and it thus might not look the program is doing anything!)
Alternatively you can use function 01h and read the characters yourself in a loop. Something like this (note it will overflow later buffers if more than 255 characters are entered):
org 0x100
start:
push cs
pop ax
mov ds, ax
mov es, ax; make sure ds = es = cs
mov di, string ; es:di points to string
cld ; clear direction flag (so stosb incremements rather than decrements)
read_loop:
mov ah, 0x01 ; Function 01h Read character from stdin with echo
int 0x21
cmp al, 0x0D ; character is carriage return?
je read_done ; yes? exit the loop
stosb ; store the character at es:di and increment di
jmp read_loop ; loop again
read_done:
mov al, '$'
stosb ; 'Make sure the string is '$' terminated
mov dx, string ; ds:dx points to string
mov ah, 0x09 ; Function 09h Print character string
int 0x21
; Exit
mov ax, 0x4c00
int 0x21
string:
times 255 db 0 ; reserve room for 255 characters
A string is just a series of characters, so you can use your int 21 code inside of a loop to get a string, one character at a time. Create a label in the data segment to hold your string, and each time you read a character, copy it to that label (incrementing an offset each time so your characters get stored sequentially). Stop looping when a certain character is read (perhaps enter).
Doing all this manually is tedious (think about how backspace will work) but you can do it. Alternatively, you can link against stdio, stdlib, etc. and call library functions to do much of the work for you.

Need help identifying and computing a number representation

I need help identifying the following number format.
For example, the following number format in MIB:
0x94 0x78 = 2680
0x94 0x78 in binary: [1001 0100] [0111 1000]
It seems that if the MSB is 1, it means another character follows it. And if it is 0, it is the end of the number.
So the value 2680 is [001 0100] [111 1000], formatted properly is [0000 1010] [0111 1000]
What is this number format called and what's a good way for computing this besides bit manipulation and shifting to a larger unsigned integer?
I have seen this called either 7bhm (7-bit has-more) or VLQ (variable length quantity); see http://en.wikipedia.org/wiki/Variable-length_quantity
This is stored big-endian (most significant byte first), as opposed to the C# BinaryReader.Read7BitEncodedInt method described at Encoding an integer in 7-bit format of C# BinaryReader.ReadString
I am not aware of any method of decoding other than bit manipulation.
Sample PHP code can be found at
http://php.net/manual/en/function.intval.php#62613
or in Python I would do something like
def encode_7bhm(i):
o = [ chr(i & 0x7f) ]
i /= 128
while i > 0:
o.insert(0, chr(0x80 | (i & 0x7f)))
i /= 128
return ''.join(o)
def decode_7bhm(s):
o = 0
for i in range(len(s)):
v = ord(s[i])
o = 128*o + (v & 0x7f)
if v & 0x80 == 0:
# found end of encoded value
break
else:
# out of string, and end not found - error!
raise TypeError
return o