Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] Reading Port pin Status

Status
Not open for further replies.

ark5230

Advanced Member level 3
Joined
Jun 29, 2009
Messages
862
Helped
163
Reputation
324
Reaction score
140
Trophy points
1,323
Location
India
Activity points
6,187
I am using Atmega32 @ 16Mhz. and new to embedded C and AVR Studis.
Wish to read status of a port pin for measuring duration of pulse.
Can any body suggest link to resource or code for detecting status of pin.
( I have problem with DDRD, PORTD and PIND and how single pin is tested in C)
Thanks in advance
 
Last edited:

You should be able to use the external interrupt or interrupt-on-change feature:

**broken link removed**

External Interrupts on an ATmega168

AVR external interrupts - INT0 example

The external interrupt can be configure to be triggered on the rising or falling edge of a pulse and then vice versa, the interrupt service routine (ISR) should be able to time the duration between events.

If you are have issues with your code, please post it using the CODE Tags so that we may examine it.


BigDog
 
OH Big guru (let me use this), thanks for such a quick reply. I am very new, Interrup is little advance. I am using delay loop for the duration. One ms dealy loop is used. The pulse is few hundred ms, this accuracy will presently suffice.
I am trying to monitor a pin. as soon as it goes high, it is polled every ms and counter is incremented till it is high. Similar approach for the low duration. I will post the test code in a while.
Thanks to alex for the link. I could not understand it but I know the value of his posts, it must be containing what I am looking for and will carefully examine details to find answer to my query.



Code:
#include <avr/io.h>
#include <util/delay_basic.h>


void Onems(uint8_t delay)
{
	//One ms delay

	uint8_t i,j;
	for(i=0;i<32;i++)
	{
		for(j=0;j<10;j++)
		{
		_delay_loop_1(32);
		}
	}
}


int main()
{
	uint16_t count1,count2;
//	uint8_t tim=250;
	//Set the PORTD7 as output
	DDRB=0B00000000;  // all bit and b4 as INPUT
	PORTB|=(1<<PB4);
	DDRD=0b10000000;  // D7 as O/P
	PORTD |=0B10000000;


	while(1)
	{
	count1=0;
	count2=0;

	while (PINB4==1)
	{
		Onems(100);
		count1=count1+10;
		Onems(10);
		count1 = count1 + 1;
		PORTD |=0B10000000;
	}

	while (PINB4==0)
	{
		Onems(100);
		count1=count2+10;
		Onems(10);
		count2 = count2 + 1;
		PORTD &=0B01111111;
	}
}
 
Last edited:

Frankly, interrupts are not as scary as they sound and are a greatly preferred method over polling.

However, I understand you are just learning the ropes, so post your code and we'll try to assist you.

After you complete the polling method, try working through the interrupt examples I've posted and I believe you find the technique quite handy.

BigDog

- - - Updated - - -

Using timer would be a better solution, then using delays and manual counter increments.

Have you used a timer in any of your projects?

BigDog
 
So Nice,
I did my PG in 1972 with valves, semiconductors were just introduced in the syllabus as junction and transistors.
I am trying to cope with things at a pace I can afford because of background. I am conversant with 8051 family (assembly only) I am gradually trying to learn embedded C. You can understand my learning is self learning so the slow pace. This is part of real project the pulse is hear beat pulse from IR sensor. Your guidance is appreciated (forum does not encourage praise, I received guidance from big people in forum including you).

- - - Updated - - -

I can easily use timers in 8051 assembly and here in C I will habe to struggle, I will certainly prefer that at the time of refinement, presently timeline forces me to settle it this way.
in fact there are posts in this forum where I have helped others using timers in 8051 assembly.

https://www.edaboard.com/threads/232358/
 
Last edited:

I could not understand it but I know the value of his posts, it must be containing what I am looking for and will carefully examine details to find answer to my query.

The macros will simplify the way you work with specific pins, I was mainly referring to the following


Code C - [expand]
1
2
3
4
5
6
// add this defines
#define SETBIT(ADDRESS,BIT) (ADDRESS |= (1<<BIT)) 
#define CLEARBIT(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT)) 
#define FLIPBIT(ADDRESS,BIT) (ADDRESS ^= (1<<BIT)) 
#define CHECKBIT(ADDRESS,BIT) (ADDRESS & (1<<BIT)) 
#define WRITEBIT(RADDRESS,RBIT,WADDRESS,WBIT) (CHECKBIT(RADDRESS,RBIT) ? SETBIT(WADDRESS,WBIT) : CLEARBIT(WADDRESS,WBIT))



Then you can do the following:

Code:
Instead of PORTB|=(1<<PB4); you can use SETBIT(PORTB,PB4);
Instead of PORTD |=0B10000000; you can use SETBIT(PORTD,7);
Instead of PORTD &=0B01111111; you can use CLEARBIT(PORTD,7);
Instead of while (PINB4==1) ([COLOR="#FF0000"]which is not valid by the way[/COLOR]) you can use while (CHECKBIT(PINB,4));

All these can help you avoid mistakes and increase readability of the code.

- - - Updated - - -

Also while (PINB4==0) is not valid , either replace it with while (!CHECKBIT(PINB,4)); or while !(PINB & 0b00010000);

PINBx are defined as

Code:
#define PINB7   7
#define PINB6   6
#define PINB5   5
#define PINB4   4
#define PINB3   3
#define PINB2   2
#define PINB1   1
#define PINB0   0

So while (PINB4==0) is the same as writing while (4==0) which is always false
 
Great !!
Alexe this seems to be the appropriate approach. As I am new to C I amy commit cilly mistakes. I could not get that these are macros saving lot of coding. My poor knowledge in C forces me to go by only those things that I know and can use it. The suggestions in post 5 are also fast efficient and reiliale approaches however I dont have teeth to cruch that stuff. I am trying to learn that alos but by that time new things would have come. Any wy could you please do the favour of correcting the code ( if it is doable) and you get time. It will really help me.
I am making those two corrections with thanks.
I think all this will answer my querry, implementing above points will solve the issue. I have one more querry for which i will create a new post.
 
Last edited:

The following delay/counter loops make no sense:

Code:
	while (PINB4==1)
	{
		Onems(100);
		count1=count1+10;
		Onems(10);
		count1 = count1 + 1;
		PORTD |=0B10000000;
	}

	while (PINB4==0)
	{
		Onems(100);
		count[COLOR="#FF0000"]1[/COLOR]=count2+10;
		Onems(10);
		count2 = count2 + 1;
		PORTD &=0B01111111;
	}

The counter increment of each loop is 110ms as well as the polling interval, if your delay routine is accurate. The Super Loop is also clearing both counters at each iteration. Is this intended? And you are missing a closing curly brace '}' at the end of the Super Loop or main() take your pick.

I would suggest the following:

Code:
	while(1)
	{
		count1=0;
		count2=0;

		while (CHECKBIT(PINB,4))
		{
			Onems(1);
			count1++;
			
			PORTD = 0b10000000;
		}

		while (!CHECKBIT(PINB,4))
		{
			Onems(1);
			count2++;
			
			PORTD = 0b0000000;
		}
	}

How are you retrieving the data? Breakpoint debugging?


BigDog
 
Last edited:
For testing purpose Port D bit 7 is used to check if it is following input or not, which the presnent code is not doing.
This is because of the mistakes in the code pointed by Big guru and Alexe.
I will implement these corrections.
There is a falacy in the delay loop and naming of the loops the delyloop Onems with argument 10 gives 1 ms delay. For the first rising part of the pulse there are few spikes, to skip those spikes initial delay of 10 ms is used (with argument of 100) and 10 is added to the count, for the rest one ms increment is used. Your corrected code clearly shows that my code is really a laymans code.

- - - Updated - - -

Big guru
In post 7 issue is raised about PINB == 0 and PINB == 1, so to be safe I will first try that (i.e. repalce corresponding instructions.)
 

By the way I noticed that you are using

Code:
#include <util/delay_basic.h>


void Onems(uint8_t delay)
{
	//One ms delay

	uint8_t i,j;
	for(i=0;i<32;i++)
	{
		for(j=0;j<10;j++)
		{
		_delay_loop_1(32);
		}
	}
}

You can use the

Code:
#include <util/delay.h>

This will give you assess to

Code:
_delay_us();
_delay_ms();

which is simpler to use and probably more accurate, all it needs to work correctly is for you to set the cpu frequency so that the loop amount in order to achieve the delay can be calculated properly

https://www.nongnu.org/avr-libc/user-manual/group__util__delay.html

- - - Updated - - -

You are probably getting overwhelmed with all that info thrown at you but give it some time and you'll get comfortable with all these
 
True, very tru!

This delay fuction will simplify many things, The delay used by me from
#include <util/delay_basic.h>
had different functionality from claim, it is claimed that at 1 MHz it is expected to give 768 micro second but with 16 MHz too it gives the same 768 (I did not try 1 MHz).
I will implement and check and use this delay.
The command SETBIT is giving a warning
../PulseRate2.c:40: warning: implicit declaration of function 'SETBIT'
Now things seem to be under control and I will make the changes and hope it will work fine.
 

The command SETBIT is giving a warning

You have to define the macros before you use them.
At the top of your c file add

Code:
#define SETBIT(ADDRESS,BIT) (ADDRESS |= (1<<BIT)) 
#define CLEARBIT(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT)) 
#define FLIPBIT(ADDRESS,BIT) (ADDRESS ^= (1<<BIT)) 
#define CHECKBIT(ADDRESS,BIT) (ADDRESS & (1<<BIT)) 
#define WRITEBIT(RADDRESS,RBIT,WADDRESS,WBIT) (CHECKBIT(RADDRESS,RBIT) ? SETBIT(WADDRESS,WBIT) : CLEARBIT(WADDRESS,WBIT))

True, very tru!

This delay fuction will simplify many things, The delay used by me from
#include <util/delay_basic.h>
had different functionality from claim, it is claimed that at 1 MHz it is expected to give 768 micro second but with 16 MHz too it gives the same 768 (I did not try 1 MHz).

The delay_loop just executes the number of loops given in the parameter, according to the cpu frequency each loop will have a different duration and you will get a different delay.
The delay_loop_1 () can give up to 768 microseconds when called to execute 256 loops, loops delay_loop_1(0);
With 16MHz you should get 768/16 us
 
DDR is to set the port for input or output
PORT is to control the pins if u set them as output
PIN is to control the pins if u set them as input
 
Yes it works!
I will test it live with signal connected.
 

Thank Alexan_e and Big guru

I tested it on hardware and it is doing what I expected. I had problem with the C code as well, now everything is fine.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top