keil c51 weird masking behaviour - microcontroller

I am trying to read two pins from a c8051f040 controller.
Reading the port directly works, but saving the same port value to a variable does not work even though the debugger shows the correct value.
// This works
if((P1 & 0xF0) == 0xa0)
{
YEL_LED = 1; //Turn on
}
else
{
YEL_LED = 0; //Turn off
}
// This does not work even though the debugger
// shows the correct value 0xa0 for the var
ORange = (P1 & 0xF0);
if(ORange == 0xa0)
{
YEL_LED = 1; //Turn on
}
else
{
YEL_LED = 0; //Turn off
}
Is this a KEIL c51 bug or is something being optimized away.

The variable was declared as char which is signed. It should be unsigned.
I got fooled by the debugger which was showing the the watch variable as unsigned.

Related

MSVC2022 17.2 address sanitizer trigger false positive on vector::push_back

I turned on Asan on my project, which is a exe project and based on webRTC.lib(release72).
Because webRTC release72 do not support Asan on windows, so the webRTC.lib can not turn on Asan, BTW, the webRTC.lib is generated by MSVC2017 while my project is generated by MSVC2022(17.2 preview).
Before I turned on Asan on my project, it works normally. then I turned on Asan, my project trigger a Asan report in webRTC h264 EncoderQueue thread:
std::vector<uint8_t> ParseRbsp(const uint8_t* data, size_t length) {
std::vector<uint8_t> out;
for (size_t i = 0; i < length;) {
// Be careful about over/underflow here. byte_length_ - 3 can underflow, and
// i + 3 can overflow, but byte_length_ - i can't, because i < byte_length_
// above, and that expression will produce the number of bytes left in
// the stream including the byte at i.
if (length - i >= 3 && !data[i] && !data[i + 1] && data[i + 2] == 3) {
// Two rbsp bytes.
out.push_back(data[i++]);
out.push_back(data[i++]);
// Skip the emulation byte.
i++;
} else {
// Single rbsp byte.
out.push_back(data[i++]);<======crash here everytime
}
}
return out;
}

Serial not reading all inputs from monitor correctly

Im trying to send inputs to Arduino MEGA using the monitor. Ive noticed that 1/6 times, the Serial skips 1 or more letters in my input. Ive tried Serial.read() and Serial.readStringUntil() but both skip input. I tried putting delay after the Serial.read() but it does nothing. I also tried doing a Serial.flush in the if(complete){...} code block but to no avail.
In this picture, "A**" was sent correctly (Ive noticed it always has as it is the 1st monitor input). But subsequent commands like the "s**100" was sent as "s*0". Is there misuse of the Serial class here? Is there a misconfiguration maybe in using the Serial monitor? (No line ending). Could it be that using other custom classes interfere with the Serial even if it didnt explicitly interact with it?
//===========================================THE IMPORTANT PART===============================================
void loop() {
digitalWrite(13, HIGH);
while (Serial.available()){
String temp = Serial.readStringUntil(';');
Serial.println(temp);
command = temp.substring(0,3);
param = temp.substring(3).toInt();
complete = true;
Serial.println("temp "+temp);
Serial.println("comm "+command);
Serial.println("para "+command);
}
//=============================================================================================================
if(complete){
Serial.println("complete");
if(command == MODE_SOLID || command == MODE_GRADIENT || command == MODE_OFF){
current_mode = command;
}
else if(command == COMMAND_BRIGHTNESS){
current_brightness = param;
}
else if(command == COMMAND_SATURATION){
current_saturation = param;
}
else if(command == COMMAND_COLOR){
current_color = param;
}
else if(command == COMMAND_RANDOM_BRIGHTNESS_UPPERLIMIT){
current_random_brightness_upper_limit = param;
}
else if(command == COMMAND_RANDOM_BRIGHTNESS_LOWERLIMIT){
current_random_brightness_lower_limit = param;
}
else if(command == COMMAND_RANDOM_SATURATION_UPPERLIMIT){
current_random_saturation_upper_limit = param;
}
else if(command == COMMAND_RANDOM_SATURATION_LOWERLIMIT){
current_random_saturation_lower_limit = param;
}
else if(command == COMMAND_RANDOM_COLOR_UPPERLIMIT){
current_random_color_upper_limit = param;
}
else if(command == COMMAND_RANDOM_COLOR_LOWERLIMIT){
current_random_color_lower_limit = param;
}
else if(command == COMMAND_COLOR){
current_color = param;
}
complete = false;
command = "";
param = 0;
}
if(current_mode == MODE_SOLID){
solid.setBrightness(current_brightness);
solid.setSaturation(current_saturation);
solid.setColor(current_color);
solid.runPattern();
}
else if(current_mode == MODE_GRADIENT){
blinkSolid.setCurrentRandomBrightnessLowerLimit(current_random_brightness_lower_limit);
blinkSolid.setCurrentRandomBrightnessUpperLimit(current_random_brightness_upper_limit);
blinkSolid.setCurrentRandomSaturationLowerLimit(current_random_saturation_lower_limit);
blinkSolid.setCurrentRandomSaturationUpperLimit(current_random_saturation_upper_limit);
blinkSolid.setCurrentRandomColorLowerLimit(current_random_color_lower_limit);
blinkSolid.setCurrentRandomColorUpperLimit(current_random_color_upper_limit);
blinkSolid.runPattern();
}
else if(current_mode == MODE_OFF){
strobePalette.runPattern();
//fill_solid( leds, NUM_LEDS, CRGB::Black);
//FastLED.show();
}
}
I've experienced similar issues with physical devices, most of the times in harsh environments or using defective wiring.
I tested your code using tinkercad with an Arduino Uno, only the communication part. This is the code I tested:
bool complete;
String command;
int param;
void setup()
{
Serial.begin(9600);
}
void loop()
{
digitalWrite(13, HIGH);
while (Serial.available()){
String temp = Serial.readStringUntil(';');
Serial.println(temp);
command = temp.substring(0,3);
param = temp.substring(3).toInt();
complete = true;
Serial.println("temp "+temp);
Serial.println("comm "+command);
Serial.println("para "+ String(param)); //I changed this line in order to see the value of "param" in the serial monitor
}
if(complete){
Serial.println("complete");
complete=false;
command="";
param=0;
}
}
I tested the code sending the string A**100;B**101;C**102;D**103; all of the parts arrived ok and they were well decoded. This is the TinkerCad output:
A**100
temp A**100
comm A**
para 100
B**101
temp B**101
comm B**
para 100
C**102
temp C**102
comm C**
para 100
D**103
temp D**103
comm D**
para 100
I also tested the code using a physical Arduino uno, and It worked as well as in Tinkercad. This is what I would do:
Let the code only with the communication part, as I did, and see how it behaves. If your code behaves ok only with the communication part, then you have something interfering in the rest of the code. It is hard to tell what could be without knowing the code of the custom clases.
If you are connecting a physical arduino to the usb port of PC, change that cable. Some defective cables may work weird and cause that kind of issues.
If you will be installing your device in a harsh environment, try to make your code resistant to those kind of errors, it is most likely that they will be present anyway. In such scenarios, I have used a starting character, an ending character and a fixed length, something like #A**100;#B**101; where # is the starting character, the semicolon (;) is the ending character, and all the commands are eight characters long. I discard all of the commands that does not fulfill those params. Using CRC is another option, but in most cases it is enough with the simple pattern I just described.

Stuck in a for loop in Arduino IDE

I'm using Arduino to look for I2C addresses, and half way through this new glitch appeared, and I don't know if it's the IDE or if I'm going insane.
I know most of this probably isn't important, but I don't know what is going on so here is my entire loop.
void loop(){
byte error, address;
int nDevices;
Serial.println("Scanning...");
nDevices = 0;
for(address = 0; address <= 255; address++ )
{
Wire.beginTransmission(address);
error = Wire.endTransmission();
Serial.print(address);
Serial.print("|");
Serial.println(error);
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("Unknow error at address 0x");
if (address<16)
Serial.print("0");
Serial.println(address,HEX);
}
delay(200);
//Serial.println(address);
}
delay(150);
Serial.println("Exiting");
if (nDevices == 0)
Serial.println("No I2C devices found\n");
else
Serial.println("done\n");
delay(30000);
exit(0);
}
As you can see in the picture I included the for loop returns to address=0 without printing anything after it, or before it in the loop(). Why is this happening?
I'm sure it has to do with you declaring address as a byte which is can be the integer 255 at max. What happens is if you add 1 to a byte value of 255, it loops around again to 0.
What happens when address = 255 and when the for loop goes back up to check the conditioning, 255 passes and address++ adds 1 to address so now address = 0.
https://www.arduino.cc/en/reference/byte
Alternatively, you could use a while loop instead and increment the address counter at the very end of the loop, followed by a test to see if it has wrapped around to zero. On the first run through of the loop, the address counter will be 1, so the loop will continue until the counter has reached 255 when the increment will wrap it around to zero and execution reaches the break statement.
byte address = 0;
while( true ) // Creating an unconditional loop
{
// Run your test here
address++;
if( !address ) // If address has wrapped around to 0, exit the loop
{
break;
}
}
...or a do/while loop, which does the same thing but may be slightly larger in some cases.
byte address = 0;
do
{
// Run your test here
address++;
} while( address ); // The loop will continue until address becomes zero again
Depending on your microcontroller, this may take a few bytes more program space though it looks like the while-loop ends up the same size as the for-loop on an ATMega328. (YMMV, of course)
On 8-bit microcontrollers however, code to manipulate ints will be slower and take up more space, so depending on your code you may still be better off by being able to stick with using a byte for your address.

Arduino command timeout

I'm currently working with a Arduino to forfill one of my DIY projects.
As it currently stands, I have my fingerprint scanner (GT-511C3) connected to my Arduino and that works great. I'm able to verify enrolled fingerprints.
The verifying of the finterprints happends via Raspberry Pi command (whom is initiated by a button press)
Logically, this means, when the button is pressed, the Raspberry Pi sends a 'validate' command to the Arduino, whom in return ask the Fingerprint scanner to run the validate command.
However, I would like to have a timeout after the validate command it sent. The timeout needs to make sure that if the button pressed (and the validate command is initated) but no one puts their finger on the machine it timeouts and reverts back to a state where it waits for the validate command.
I'm not able to complete this. This is the code I've tried:
#include "FPS_GT511C3.h"
#include "SoftwareSerial.h"
FPS_GT511C3 fps(4, 5);
int val = 0;
void setup()
{
Serial.begin(9600);
delay(100);
fps.Open();
fps.SetLED(false);
}
void loop(){
if (Serial.available() > 0) {
Continue:
if(Serial.find("validate")){
fps.SetLED(true);
do {
++val;
delay(100);
}
while(fps.IsPressFinger() == false || val > 150);
if(val <= 150){
fps.SetLED(false);
goto Continue;
}
if (fps.IsPressFinger()){
fps.CaptureFinger(false);
int id = fps.Identify1_N();
if (id <200)
{
Serial.print("Verified ID:");
Serial.println(id);
fps.SetLED(false);
}
else
{
Serial.println("Finger not found");
fps.SetLED(false);
}
}
else
{
Serial.println("Please press finger");
}
delay(100);
}
}
}
The code otherwise works fine, if the finger is placed and validated, it turns off and goes back to waiting for another validate command.
Any help would be greatly appreciated!
First, get rid of the label and goto. There is no justification for it here; it's considered bad programming practice and shouldn't be used unless you know exactly what you're doing. Only in Assembly is it okay to use goto (equivalent to JMPs) liberally.
Next, your while condition is wrong. If you try to interpret it, you'll notice it doesn't make any sense:
Wait for as long as nobody has placed a finger or if the timeout has expired.
What you probably want is:
Wait for as long as nobody has placed a finger and the timeout has not expired.
which translates to:
while(fps.IsPressFinger() == false && val < 150);
The IF condition that follows, is also wrong and should mean:
if the timeout has expired
translating to:
if(val >= 150){
fps.SetLED(false);
val = 0;
continue;
}
Notice the use of the continue keyword which restarts a loop. To make it legit, change if (Serial.available() > 0) to while (Serial.available() > 0).

Reading Soft_Uart & Hardware Uart # same time

OK, so i have accomplished creating a software and hardware UART on PIC18f8680 in MikroC compiler. The Soft_Uart uses timer0 for interrupt and breaks the Soft_UART_read() line by a function called Soft_uart_Break().
everything is working fine, when i read a single character from both uart. but when i send a string on hardware uart, the string doesn't gets reads properly by these lines;
UART1_Read_Text(buffer, "OK", 100);
UART1_Write_Text(buffer);
I've found out whats causing this problem. that is, my main while loop gets stuck in Soft_UART_read() until it gets break by an interrupt. while its stuck over there, the hardware uart doesn't gets proper time to read the whole string, so as a result it displays some of the characters of that string.
how can i overcome this ? do i need to use a separate interrupt for hardware uart aswel ? or what ? any help would be highly appreciated.
here is a snip of my code;
void main() {
INTCON.GIE=1; //globle interrupt enable
INTCON.PEIE=1; //peripharel interrupt enable
INTCON.TMR0IF = 0x0; //Clear timer0 overflow interrupt flag
INTCON.TMR0IE = 1; //enable the timer0 by setting TRM0IE flag
T0CON.TMR0ON = 1; // Timer0 On/Off Control bit: 1=Enables Timer0 / 0=Stops Timer0
T0CON.T08BIT = 0; // Timer0 8-bit/16-bit Control bit: 1=8-bit timer/counter / 0=16-bit timer/counter
T0CON.T0CS = 0; // TMR0 Clock Source Select bit: 0=Internal Clock (CLKO) / 1=Transition on T0CKI pin
T0CON.T0SE = 0; // TMR0 Source Edge Select bit: 0=low/high / 1=high/low
T0CON.PSA = 1; // Prescaler Assignment bit: 0=Prescaler is assigned; 1=NOT assigned/bypassed
T0CON.T0PS2 = 0; // bits 2-0 PS2:PS0: Prescaler Select bits
T0CON.T0PS1 = 1;
T0CON.T0PS0 = 1;
TMR0H = 0xBD; // preset for Timer0 MSB register
TMR0L = 0xCD; // preset for Timer0 LSB register
while(1) {
data1 = Soft_UART_Read(&error);
Soft_UART_Write(data1);
if (data1 == 'b') {
for(x = 0; x <= strlen(alive); x++) {
Soft_UART_Write(alive[x]);
}
}
if (UART1_Data_Ready()) { // If data is received,
UART1_Read_Text(buffer, "OK", 100); // reads text until 'OK' is found
UART1_Write_Text(buffer); // sends back text
/*if (uart_rd == 'a') {
UART1_Write_Text("\rSensor 1 data\r");
}*/
//else
//UART1_Write(uart_rd); // and send data via UART
}
}
}
I had the same issue. Some of the example code and documentation in the MikroC manual seems to contradict itself.
The prototype is:
void UARTx_Read_Text(char *Output, char *Delimiter, char Attempts);
Your delimiter should be:
char delimit[] = "OK";
UART1_Read_Text(&dataIn,&delimit,attempts);
If you know the size of the data being received attempts should correspond to this.

Resources