CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Read-Write-Modify issues
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Arakel



Joined: 06 Aug 2016
Posts: 107
Location: Moscow

View user's profile Send private message Visit poster's website AIM Address

Read-Write-Modify issues
PostPosted: Sat Dec 24, 2016 11:14 am     Reply with quote

Good day to everyone and happy holidays!

I have been missing for a long time, thank you for all your help so far and I have another interesting issues that I need solved :D.

Despite that I understand RWM issues, I want to know is there any way to use input_x and output_x functions if I put a delay of 1ms before them? Despite that I believe that should be enough I am not certain. Does it depend on the current microcontroller, the clock speed, the technology flash or EEPROM and others if there are any?

Thank you for your support!
_________________
Yo! I love learning and technology! I just do not have experience so do not be angry if I ask a stupid question about a detail! From so much to remember sometimes I forget the details in order to remember the big problems!
temtronic



Joined: 01 Jul 2010
Posts: 9226
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Dec 24, 2016 3:06 pm     Reply with quote

you should post the PIC type you're using(some handle RMW differently) as well as a small compilable program to show us what you want to do.
As well, type of speed you need,what's being controlled, etc.

Jay
Arakel



Joined: 06 Aug 2016
Posts: 107
Location: Moscow

View user's profile Send private message Visit poster's website AIM Address

PostPosted: Sat Dec 24, 2016 3:25 pm     Reply with quote

I am trying to understand how to do it by myself, not to need to ask every time will RWM issues work on this microcontroller or not. But here is what is you asked for.

Code:

//We display the value of 1 sensor on the 7 segment display. We have 4 //sensors in total.

#include <16F690.h>

#fuses MCLR, NOPROTECT, NOWDT, INTRC_IO
#use delay(clock=4M)

unsigned int8 Output;
unsigned int8 i;
unsigned int8 Sensor_PIN_A0, Potentiometer_PIN_A1, Sensor_PIN_A2, Potentiometer_PIN_A3;
   unsigned int8 FinalFormOfThePORTCOutput[60] =
   {
   0b00000000, // 0
   0b00000001,
   0b00000010,
   0b00000011,
   0b00000100,
   0b00000101,
   0b00000110,
   0b00000111,
   0b00001000,
   0b00001001,
   0b00010000, // 10
   0b00010001,
   0b00010010,
   0b00010011,
   0b00010100,
   0b00010101,
   0b00010110,
   0b00010111,
   0b00011000,
   0b00011001,
   0b00100000, // 20
   0b00100001,
   0b00100010,
   0b00100011,
   0b00100100,
   0b00100101,
   0b00100110,
   0b00100111,
   0b00101000,
   0b00101001,
   0b00110000, // 30
   0b00110001,
   0b00110010,
   0b00110011,
   0b00110100,
   0b00110101,
   0b00110110,
   0b00110111,
   0b00111000,
   0b00111001,
   0b01000000, // 40
   0b01000001,
   0b01000010,
   0b01000011,
   0b01000100,
   0b01000101,
   0b01000110,
   0b01000111,
   0b01001000,
   0b01001001,
   0b01010000, // 50
   0b01010001,
   0b01010010,
   0b01010011,
   0b01010100,
   0b01010101,
   0b01010110,
   0b01010111,
   0b01011000,
   0b01011001,
   };

void main()

   setup_comparator(NC_NC_NC_NC);
   setup_adc(ADC_CLOCK_DIV_16);
   setup_adc_ports(sAN0|sAN1|sAN2|sAN3);

   while(1)
   {
      set_adc_channel(0);
      for(i=0; i<15; i++)
      {
      Sensor_PIN_A0 = read_adc();
      if( Sensor_PIN_A0 != Sensor_PIN_A0)
      i=0;
      }
     
      set_adc_channel(1);
      for(i=0; i<15; i++)
      {
      Potentiometer_PIN_A1 = read_adc();
      if(Potentiometer_PIN_A1 != Potentiometer_PIN_A1)
      i=0;
      }
     
      set_adc_channel(2);
      for(i=0; i<15; i++)
      {
      Sensor_PIN_A2 = read_adc();
      if(Sensor_PIN_A2 != Sensor_PIN_A2)
      i=0;
      }
     
      set_adc_channel(3);
      for(i=0; i<15; i++)
      {
      Potentiometer_PIN_A3 = read_adc();
      if (Potentiometer_PIN_A3 != Potentiometer_PIN_A3)
      i=0;
      }
     
      delay_ms(1);
      if(input(PIN_b7) == 0)
      Output = (Sensor_PIN_A0 - 559)/2;
      output_c(FinalFormOfThePORTCOutput[Output]);
     
      delay_ms(1);
      if(input(PIN_B6) == 0)
      Output = (Potentiometer_PIN_A1 - 559)/2;
      output_c(FinalFormOfThePORTCOutput[Output]);
     
      delay_ms(1);
      if(input(PIN_B5) == 0)
      Output = (Sensor_PIN_A2 - 559)/2;
      output_c(FinalFormOfThePORTCOutput[Output]);
     
      delay_ms(1);
      if(input(PIN_B4) == 0)
      Output = (Potentiometer_PIN_A3 - 559)/2;
      output_c(FinalFormOfThePORTCOutput[Output]);
     
      delay_ms(1000);
     
   }
}

_________________
Yo! I love learning and technology! I just do not have experience so do not be angry if I ask a stupid question about a detail! From so much to remember sometimes I forget the details in order to remember the big problems!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Dec 25, 2016 10:33 am     Reply with quote

I don't see any RMW issues in your code. On PortA, you are doing analog
reads only. No writes. On PortB, you are doing digital reads only, with
no writes. On PortC, you are writing the entire port at once and not
ever reading from it.
Arakel



Joined: 06 Aug 2016
Posts: 107
Location: Moscow

View user's profile Send private message Visit poster's website AIM Address

PostPosted: Sun Dec 25, 2016 12:14 pm     Reply with quote

Thanks for the confirmation but can you tell me if there are read and write
operations on the same PORT, what are the options and how to avoid problems?

1. If you perform the same operations on the same ports, there is one whole register for PORT_B, PORT_C, PORT_A and so on and there can be no read write modify issues?

2. RWM issues are applied when when you perform different operations on 1 register and can lead to reading the ports status from the exit instead of the register.

-How much time does it take normally for the PIC to change the output levels and if necessary is 1mS delay enough to avoid problems?

-Are there any other things that can avoid or cause RWM issues?

-Is there an inside capacitor or some capacitance on the pins and buses(cables) and how much time is it necessary to avoid that any problem?

-How much time is it necessary in order to avoid all RWM issues when using funcions like input, output_high(); ?
_________________
Yo! I love learning and technology! I just do not have experience so do not be angry if I ask a stupid question about a detail! From so much to remember sometimes I forget the details in order to remember the big problems!
temtronic



Joined: 01 Jul 2010
Posts: 9226
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Dec 25, 2016 12:18 pm     Reply with quote

OK , maybe I'm not looking at this correctly but.....

if( Sensor_PIN_A0 != Sensor_PIN_A0)

WHAT is the purpose of this ?

Jay
Arakel



Joined: 06 Aug 2016
Posts: 107
Location: Moscow

View user's profile Send private message Visit poster's website AIM Address

PostPosted: Sun Dec 25, 2016 12:23 pm     Reply with quote

As far as I can remember in C you can do this:

X= X +B;

That means that the old value of X is summed with B and we get the new value of X.

Also it should be possible to compare the old value of X with the new value of X and if they are different reduce i to 0;

if(X != X)
i=0;

Do you think it is not accurate?
_________________
Yo! I love learning and technology! I just do not have experience so do not be angry if I ask a stupid question about a detail! From so much to remember sometimes I forget the details in order to remember the big problems!
temtronic



Joined: 01 Jul 2010
Posts: 9226
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Dec 25, 2016 1:12 pm     Reply with quote

44: if(x!=x) y=0;
0246 5030 MOVF 0x30, W, ACCESS
0248 5C30 SUBWF 0x30, W, ACCESS
024A A4D8 BTFSS 0xfd8, 0x2, ACCESS
024C 6A31 CLRF 0x31, ACCESS

This is the code I get....

The if statement reads as follows..

IF ( x does not equal x ) THEN y becomes 1;

There is ONLY one memory location associated to 'x', 0x30.
There isn't a 'last value of x' temporary location...

The machine code 246, 248 says
1) move the contents of file F( RAM location 0x30) into W ( the Working register)
2) subtract the contents of the file F from the Working register

based on the outcome, either jump or set Y to 1.

Now I am interested in that the compiler didn't 'see' that X!=X can never be true and so just do a NOP.

Maybe I'm reading this all wrong as I haven't had any turkey yet today ??
Arakel



Joined: 06 Aug 2016
Posts: 107
Location: Moscow

View user's profile Send private message Visit poster's website AIM Address

PostPosted: Sun Dec 25, 2016 2:36 pm     Reply with quote

temtronic wrote:
44: if(x!=x) y=0;
0246 5030 MOVF 0x30, W, ACCESS
0248 5C30 SUBWF 0x30, W, ACCESS
024A A4D8 BTFSS 0xfd8, 0x2, ACCESS
024C 6A31 CLRF 0x31, ACCESS

This is the code I get....

The if statement reads as follows..

IF ( x does not equal x ) THEN y becomes 1;

There is ONLY one memory location associated to 'x', 0x30.
There isn't a 'last value of x' temporary location...

The machine code 246, 248 says
1) move the contents of file F( RAM location 0x30) into W ( the Working register)
2) subtract the contents of the file F from the Working register

based on the outcome, either jump or set Y to 1.

Now I am interested in that the compiler didn't 'see' that X!=X can never be true and so just do a NOP.

Maybe I'm reading this all wrong as I haven't had any turkey yet today ??


I can not confirm or deny! Do you have any suggestion on how to make the debouncing for the ADC if it is even necessary?

The new value has to be compared with the old value and if there is a difference do nothing. The idea is to avoid sudden spikes of the ADC pin and random capacitances.

For a digital I/O pin I know it is like this:

Code:

for (db_count=0; db_count<15; db_count++)
{
delay_ms(1);         //sample every 1 ms
if (input(GP3)==0)      //if button down (GP3 low)
db_count=0;         //restart count
}


I think that here a filter will really apply. The LM335 sensor is directly connected to the PIN, without a capacitor or anything else to filter the voltage, therefore there will be some random spikes from radio frequencies, wi-fi and so on.
_________________
Yo! I love learning and technology! I just do not have experience so do not be angry if I ask a stupid question about a detail! From so much to remember sometimes I forget the details in order to remember the big problems!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Dec 25, 2016 6:33 pm     Reply with quote

Quote:

The idea is to avoid sudden spikes of the ADC pin. I think that here a
filter will really apply.

See this thread:
http://www.ccsinfo.com/forum/viewtopic.php?t=54903&highlight=olympic+filter
Ttelmah



Joined: 11 Mar 2010
Posts: 19513

View user's profile Send private message

PostPosted: Mon Dec 26, 2016 2:41 am     Reply with quote

As a comment, The 'point' about RMW, is if the voltage on the pin hasn't actually got to the level it is meant to be.

Now the 'classic' is to do with the way the PIC works internally. If you perform a write immediately followed by a read on the same port. The actual 'write' takes place as the last internal clock cycle of the first instruction. The 'read' then occurs at the start of the second clock cycle of the next instruction (each instruction is four clocks).
Now if you have a pin driving into say first an 'overload' (so when set to '1' it only actually pulls up to perhaps 2v - perhaps feeding an LED without a current limit resistor), then you will permanently get RMW problems. On 'capacitance' though, at normal levels of a few hundred pF max, then even 1uSec of delay will be enough for the signal to get to the desired level. Anything involving mSec, would imply that you were massively overloading the pin.

Avoiding it. First, maintain an internal variable storing what you want on the register, and update this, then write this to the port. On the PIC18, this is why the output 'latch' is available separately to the actual 'port'.

Anyway the problem was actually nothing to do with RMW.

I'd stand firmly by the suggestion in the thread PCM_programmer pointed to, of the Olympic average. However pay very specific attention to the comment about 'know your noise'.
temtronic



Joined: 01 Jul 2010
Posts: 9226
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Dec 26, 2016 6:14 am     Reply with quote

Mr. T's last paragraph is critical to implementing a stable project.

The Olympic averaging code is great for temperature sensors ! It's small, fast, code that does exactly what you need.

You also should read the LM335 data sheet, look at 'applications' ,etc.
If the sensors are a long distance from the PIC, I urge you to add a 'rail to rail' OPamp AT THE SENSOR location. This 'unity buffer (gain of 1)' will then drive the temp signal down the wire to the PIC. The ones I use have a double T- filter added. You can easily have 25 meters of telephone 'quad' wire as hookup and still get accurate results.
At the very, very least add a .68mfd cap to the ADC input pins to filter out some noise.

Jay
Arakel



Joined: 06 Aug 2016
Posts: 107
Location: Moscow

View user's profile Send private message Visit poster's website AIM Address

PostPosted: Mon Dec 26, 2016 12:18 pm     Reply with quote

Thanks!

Now I actually understand how the instructions go. That means 4MHz internal clock is 250nS for 1 instruction by 4MHz, so for 1MHz we will have 4*250nS=1uS. Meaning 4 instructions will be carried for 1uS with 3% accuracy from the internal oscilator?

Is it that 1 instruction is carried for 4 cycles or that the instruction clock is reduced by 4? I am guessing that the REGISTER is just connected to the internal hardware and depending on the combination something is started?

I know the processor should be as close as possible to the sensor. I was reading the datasheet :D.

I also know about shadow registers but I needed to use only one pin without a shadow register.

One repeater is enough for 25 meters?
Iin = Iout = Uin/R1 ?
That means 3V/R1, so I get 3V/10 Ohms = 300mA
300mA * 3V = 900mW for the resistor
Is this really enough?
Otherwise I will need 2 * 5Watt resistors, even 3.

Olympic average-
http://www.daycounter.com/LabBook/Moving-Average.phtml

So basically we sum toghether all 10 samples, if there is a sample greater than the others or smaller it is removed. Meaning the maximum positive spike and maximum negative spikes are removed and we average the rest?
We need to remove only 2 samples because it is good to divide by 8.
If we want to account for more that 2 spikes we should increase the samples to 12?

Why 68mF should it not be 100nF in paralel with 100pF?

I guess I should account for different noises and their frequency in order to know my noise, because my methods might not be good enough and like this I can spare methods?
_________________
Yo! I love learning and technology! I just do not have experience so do not be angry if I ask a stupid question about a detail! From so much to remember sometimes I forget the details in order to remember the big problems!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Dec 26, 2016 12:36 pm     Reply with quote

Quote:
That means 4MHz internal clock is 250nS for 1 instruction by 4MHz,

No. At 4 MHz, 1 instruction cycle is 1 usec. In most cases, you get one
instruction per microsecond. (Some instructions take two instruction
cycles, such as any instruction that jumps to a new address).

The rule is, divide the PIC's clock by 4 to get the instruction cycle clock.
If the PIC is running at 4 MHz, the instruction clock is 1 MHz.
Arakel



Joined: 06 Aug 2016
Posts: 107
Location: Moscow

View user's profile Send private message Visit poster's website AIM Address

PostPosted: Mon Dec 26, 2016 12:47 pm     Reply with quote

PCM programmer wrote:
Quote:
That means 4MHz internal clock is 250nS for 1 instruction by 4MHz,

No. At 4 MHz, 1 instruction cycle is 1 usec. In most cases, you get one
instruction per microsecond. (Some instructions take two instruction
cycles, such as any instruction that jumps to a new address).

The rule is, divide the PIC's clock by 4 to get the instruction cycle clock.
If the PIC is running at 4 MHz, the instruction clock is 1 MHz.


So most instructions are carried for 1 cycle of 1uS because of the optimised 14bit harvard architecture like it is said in the datasheet? Then I have to account for how long will it take the PIC to rise the output levels and see is 1 instruction enough or not. If it is not like with the newer and faster PICs I need a delay cycle. Thanks I will see what will happen.
_________________
Yo! I love learning and technology! I just do not have experience so do not be angry if I ask a stupid question about a detail! From so much to remember sometimes I forget the details in order to remember the big problems!
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group