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.

PIC10F220 RC filter first order by numerical simulation in the microcontroller

Status
Not open for further replies.
the bug is on (movlw .15) --->movlw D'15'


Code:
;**********************************************************************
;*  ********************Programme pricnipal********************
;**********************************************************************
Wait
	movf TMR0,f			;set Z in STATUS if TMR0 = 0
	btfss STATUS,Z		        ;bit test the Z bit, skip if set (= Zero)
	goto Wait			        ;not zero yet so keep checking

	decfsz Delay,f		         ;subtract 1 from Delay and see if zero
	goto Wait			        ;not reached zero yet so keep checking

	                                        ;'Delay' has reached zero so ~1 second has elapsed
	movlw D'15'			;reload 'Delay' again
	movwf Delay                       ; code to read the ADC comes next

- - - Updated - - -

the bug is on (movlw .15) --->movlw D'15'


Code:
;**********************************************************************
;*  ********************Programme pricnipal********************
;**********************************************************************
Wait
	movf TMR0,f			;set Z in STATUS if TMR0 = 0
	btfss STATUS,Z		;bit test the Z bit, skip if set (= Zero)
	goto Wait			;not zero yet so keep checking

				;reload 'Delay' again
	movwf Delay                    
    ; code to read the ADC comes nextdecfsz Delay,f		;subtract 1 from Delay and see if zero
	goto Wait			;not reached zero yet so keep checking

	;'Delay' has reached zero so ~1 second has elapsed
	movlw D'15'

- - - Updated - - -

Code:
;**********************************************************************
;*  ********************Programme pricnipal********************
;**********************************************************************
Wait
	movf TMR0,f			;set Z in STATUS if TMR0 = 0
	btfss STATUS,Z		;bit test the Z bit, skip if set (= Zero)
	goto Wait			;not zero yet so keep checking

	decfsz Delay,f		;subtract 1 from Delay and see if zero
	goto Wait			;not reached zero yet so keep checking

	;'Delay' has reached zero so ~1 second has elapsed
	movlw D'15'			;reload 'Delay' again
	movwf Delay
	; code to read the ADC comes next
 
Last edited by a moderator:

I thing that first step about communication for LCD we must the Pin declare and variable initializes
Code:
;**********************************************************************
;*  ********************Variable declare                       ********************
;**********************************************************************
D1            EQU        0X20    
D2            EQU        0X21    
D3            EQU        0X22    
D4            EQU        0X23    
D5            EQU        0X24    
D6            EQU        0X25

That Right ?
 

No!
MPLABX allows 'D' or '.' before a number to indicate it is decimal. The bug is trickier than that and there is nothing wrong with the instructions I gave you.
The problem is this:

I already mentioned the ADC only takes 0.00013 seconds to take a reading so if you use the one second delay, read the ADC, store the result and then wait for another second before repeating, the delay will fail. The reason is TMR0 is counting relatively slowly so when you return to the routine it will not have had time for the count to increase, it will still be zero. That will make it drop through to the 'decfsz' line stright away instead of waiting for TMR0 to complete another loop. The fix is easy, we need to add new lines to ensure TMR0 is not zero before using the 'Wait' routine.
Code:
	list      p=10F220            ; list directive to define processor
	#include <p10F220.inc>        ; processor specific variable definitions

	__CONFIG   _MCLRE_ON & _CP_OFF & _WDT_OFF & _MCPU_OFF & _IOFSCS_4MHZ

; '__CONFIG' directive is used to embed configuration word within .asm file.
; The lables following the directive are located in the respective .inc file.
; See respective data sheet for additional information on configuration word.

;***** VARIABLE DEFINITIONS
    cblock    0x09

    Delay         ;variable for the delay ,to make delays
    Counter       ;variable to count how many measurements
    LCD_data      ;hold the data to be sent to the LCD 
    Counter_data   ; hold the counter for the bits as they are sent to the LCD
   
    endc


;**********************************************************************
	ORG     0x000             ; coding begins here
	movwf   OSCCAL         ; update register with factory cal value

start
	clrf LCD_data
	clrf Counter_data
	clrf Counter
	clrf Delay

; remaining code goes here

Wait
	movlw .15			;reload 'Delay' again
	movwf Delay
	movlw 1			;give TMR0 a start value
	movwf TMR0
Wait1
	movf TMR0,f		;set Z in STATUS if TMR0 = 0
	btfss STATUS,Z		;bit test the Z bit, skip if set (= Zero)
	goto Wait1			;not zero yet so keep checking
	
	decfsz Delay,f		;subtract 1 from Delay and see if zero
	goto Wait1			;not reached zero yet so keep checking
	return

I have done several things:
1. loaded TMR0 with a starting value of 1 at the beginning of the routine
2. moved the lines so 'Delay' is set before it is used
3. added another label 'Wait1' and changed the calls to it so the loop runs after Delay and TMR0 have been initialized
4. added a 'return' instruction at the end.

The return instruction makes it a 'universal' delay sub-routine that can be used anywhere in the program with the instruction 'call Wait'. The subroutine will return when about 1 second has elapsed. There is something to be aware of in the PIC10 processors - each subroutine 'call' requires it to store the address it goes back to after the 'return' instruction and these simple processors only have capacity to store TWO addresses. We call it a two deep stack, it limits you to making one 'call' while already in a subroutine. It saves the return address of the first subroutine, then the address of a second subroutine. Any further calls will overwrite the first address and almost certainly crash the program. Be careful with nested subroutines!

Lets write a new routine to read the voltage using the ADC (Analog to Digital Converter). You already know the code to configure ADCON0 and OPTION so you can add those lines to "remaining code goes here" in the program. The ADC is a circuit built in the silicon of the PIC, you route a voltage from one of the pins using ADCON0, tell it to start measuring it and it completes with a numeric version of the voltage. It doesn't tell you what the voltage actually is, it returns an 8-bit number between 0 for 0V and 255 for maximum voltage. In this PIC the maximum voltage is the VDD (positive supply line) voltage. For example, if you use a 5V supply and gradually increase the voltage on GP0, the ADC result would go up from zero to 255.

The ADC module needs to be told when to start a measurment, in some applications you have to synchronize it to some event but here I assume the wind speed voltage is always present so it can be measured at any time. To start the ADC, all you do is make the GO/-DONE bit in ADCON0 equal '1'. It stays at '1' until the ADC has finished measuring the voltage, it's a fast process, when finished it makes GO/-DONE zero again by itself and the value it measured is present in the ADRES (Analog to Digital RESult) register.

So the process is:
1. make sure the input pin is configured for analog use
2. select that pin as the input to the ADC
3. set the GO/-DONE bit in ADCON0
4. wait for GO/-DONE to return to zero
5. read the ADRES register

I propose this code, note the use of the 'bsf' (Bit Set in File) instruction and how I use the names of the register and bit instead of their numbers. There is an equivalent 'bcf' (Bit Clear in File) instruction to make a bit zero.
Code:
; read the voltage on the analog input pin, return result in W
ReadADC
	bsf ADCON0,GO_NOT_DONE	;start measuring the voltage
ADC_Wait
	btfsc ADCON0,GO_NOT_DONE ;skip next instruction if GO/-DONE is zero
	goto ADC_Wait		;not finished yet!
	movf ADRES,W		;copy the result to W
	return
See if you can understand it. I made it a subroutine again. If you add it and assemble the code you will have reached the stage where the PIC is initialized, has a delay routine and can measure voltages - all in less than 20 bytes of code!

Brian.
 

SO


Code:
list     p=10F220            ; list directive to define processor
	#include <p10F220.inc>        ; processor specific variable definitions

	__CONFIG   _MCLRE_ON & _CP_OFF & _WDT_OFF & _MCPU_OFF & _IOFSCS_4MHZ


;***************************************************************************
; *******************microcontroller initialization***************************************
;***************************************************************************

	movlw			b'00001001' 	;sets GP1 and GP2 as Outputs
    TRIS			GPIO
    movlw           0x41
    movwf           ADCON0

    movlw 0xC7
    option
;****************************************************************************	
;***** VARIABLE DEFINITIONS**************************************************
;****************************************************************************
    cblock    0x09

    Delay         ;variable for the delay ,to make delays
    Counter       ;variable to count how many measurements
    LCD_data      ;hold the data to be sent to the LCD 
    Counter_data   ; hold the counter for the bits as they are sent to the LCD
   
    endc
;**********************************************************************
;******************* coding begins*************************************
;**********************************************************************
	ORG     0x000             ; coding begins here
	movwf   OSCCAL         ; update register with factory cal value

start
	clrf LCD_data
	clrf Counter_data
	clrf Counter
	clrf Delay

;***********************************************************************
;                       remaining code goes here
;***********************************************************************
Wait
	movlw .15			;reload 'Delay' again
	movwf Delay
	movlw 1			;give TMR0 a start value
	movwf TMR0
Wait1
	movf TMR0,f		;set Z in STATUS if TMR0 = 0
	btfss STATUS,Z		;bit test the Z bit, skip if set (= Zero)
	goto Wait1			;not zero yet so keep checking
	
	decfsz Delay,f		;subtract 1 from Delay and see if zero
	goto Wait1			;not reached zero yet so keep checking
	return
;********************************************************************
; read the voltage on the analog input pin, return result in W
;********************************************************************

ReadADC
	bsf ADCON0,GO_NOT_DONE	;start measuring the voltage
ADC_Wait
	btfsc ADCON0,GO_NOT_DONE ;skip next instruction if GO/-DONE is zero
	goto ADC_Wait		;not finished yet!
	movf ADRES,W		;copy the result to W
	return

- - - Updated - - -

after reading the voltage on the analog input pin, I suppose we must now coding thé filter
 

hello,


I don't have a PIC10F220 , even no ISIS simultaor,
but i did some test , with mikroC, wich can accept asm code inside C langage
and i wrote this.. for averaging up to 256 measures wich give result in Beaufort range 0 to 9.
you can use this ,because it is quiet standard asm PIC (even i used a 18F2550 at 48MHz!)

to get the Beaufort value and 1seconde timer .. use of 7 bytes of RAM
i tested it under mikroC environment..
maybe some instruction can differe a litle bit .. like Right Rotation trough Carry (RRC)
but easy to adapt with 10F220 data sheet instructions list.

View attachment Average_ADC.zip

with integer value, and 8 bits only, it is not evident to get a very linear correspondance
with binary and decimal (step 0 to 9)
so some artifices are added to keep 0 value and add the 9th step
without using integer 16 bits and more RAM...


Points_Beaufort_conv.jpg
 

That is an interestng method. You accumulate 256 measurements and count the number of times the overflow flag is set then divide the result by 32 to scale the result to lie between 0 and 9. If it's > 8 you make it -1 then add 1 to the result. I will have to look into that deeper but it might be a good solution.

Thierry, please do not use this code on the PIC10F220, it uses instructions that PIC will not understand but if the method is viable I can convert it so it will run on that processor.

Brian.
 

:thinker::thinker::oops: the time with me is already scarce with this topic ,I have read everything Possible but I find no solutions
 

Is there a possibility or a simple way to modify or change the Paulfjujo’s code so that its compatible with my microcontroller? I find no solutions:bang:
 

The 10F220 only has 33 instructions so it isn't difficult to learn! Take a close look at all the instruction details in chapter 9 of the data sheet.

I have been working away unexpectedly so I have not had much time to help you but here is code I have written and simulated, it works so far but I have not added the LCD routine yet.
Code:
;***** VARIABLE DEFINITIONS
    cblock    0x10

    Delay			;variable for the delay ,to make delays
    Counter			;count the number of measurements
	Total			;accumulation of ADC measurements
	Average			;average value of the measurements
    Temporary		;use for holding partial results in calculations
	LCD_data		;hold the data to be sent to the LCD 
    Counter_data	;hold the counter for the bits as they are sent to the LCD
   
    endc


;**********************************************************************
	ORG     0x000             ; coding begins here
	movwf   OSCCAL            ; update register with factory cal value

start
	clrf LCD_data
	clrf Counter_data
	clrf Counter
	clrf Delay
	
	movlw			b'00001001' 	;sets GP1 and GP2 as Outputs
    TRIS			GPIO      
    movlw           0x41
    movwf           ADCON0
	movlw			0xC7
	option

MainLoop
	movlw 4
	movwf Counter
	clrf Total
SumLoop
	call Wait			;one second delay
	call ReadADC		;take a measurement	
	movwf Temporary		;store the result
	bcf STATUS,C		;must not shift carry bit into result
	rrf	Temporary,f		;divide result by 2
	bcf STATUS,C		;must not shift carry bit into result
	rrf Temporary,w		;divide by 2 with result in W
	addwf Total			;add the result to the average
	decfsz Counter,f	;see if 4 measurements have been averaged
	goto SumLoop	;no - so repeat until all 4 taken
	;Total = the sum of 4 readings taken at 1 second intervals
	
	call LCDUpdate		;update the display
	goto MainLoop
	
	; remaining code goes here

Wait
	movlw .15			;reload 'Delay' again
	movwf Delay
	movlw 1				;give TMR0 a start value
	movwf TMR0
Wait1
	movf TMR0,w			;set Z in STATUS if TMR0 = 0
	btfss STATUS,Z		;bit test the Z bit, skip if set (= Zero)
	goto Wait1			;not zero yet so keep checking
Wait2
	movf TMR0,w			;set Z in STATUS if TMR0 = 0
	btfsc STATUS,Z		;wait for TMR0 to be NOT zero
	goto Wait2
	decfsz Delay,f		;subtract 1 from Delay and see if zero
	goto Wait1			;not reached zero yet so keep checking
	return

; read the voltage on the analog input pin, return result in W
ReadADC
	bsf ADCON0,GO_NOT_DONE	;start measuring the voltage
ADC_Wait
	btfsc ADCON0,GO_NOT_DONE ;skip next instruction if GO/-DONE is zero
	goto ADC_Wait		;not finished yet!
	movf ADRES,W		;copy the result to W
	return

; show the scaled result on the LCD
LCDUpdate
	
	END                       ; directive 'end of program'

I did not use Paulfjujo's code although with some simple changes it would work. His code adds 256 ADC readings together then divides the result to make it fall in the 0 to 9 range. I decided to divide the individual results first then add them together. The mathematical result is the same but my method may be more adaptable because it does not constrain you to taking 256 measurements every time.

Put my code in MPLABX and see if you can add a 'watch' window to see the contents of the registers. If you run it or single step it you can see exactly what each instruction does and how it changes the values in the registers. See if you can work out the exact time the 'Wait' routine takes, it isn't exactly 1 second but very close, with MPLABX you can add a breakpoint at the start and end of the Wait routine and use the stopwatch to see the exact time taken between them.

Brian.
 

hello
Somebody can tell me please how I can set the LCD-SPI software, since I try to display data on LCD, but I cannot do it, it does not work
 

Hint: before the LCD will display anything you have to initialize it.
Another hint: ignore the asm code in the Libstock link and follow the '.c' code instead.

Remember making a pin = 1 in C is the same as using 'bsf' in assembler and making a pin = 0 is the same as 'bcf'.
You have examples already of how to create loops.

Brian.
 

I am attaching a code. It doesn't compile. There are few errors. They have to be fixed. Maybe betwixt can fix the errors and make it work. I am not an experienced ASM programmer. I have tried to port the 2 Wire LCD C code to ASM code for PIC10F220. I was not successful.
 

Attachments

  • 2 Wire LCD ASM PIC10F220.rar
    11.3 KB · Views: 38

His is what I try to do for the LCD is it correct? and I do not understand the difference between LCD and LCD-SPI, How to code a LCD-SPI?



Code:
; LCD TRIS
Ban1                          ;lcd RW leg is grounded, so we'll only write data to the lcd, and never read.

    movlw b'11000000'
    movwf tris_lcd    ;all output ports 

LCD_int

 ;use both lines of the display
    movlw b'00000010' ;mode 4 bits
    movwf port_lcd
    call e_pulse
    movlw b'00000010' ;mode 4 bits
    movwf port_lcd
    call e_pulse

;allow display and hide the cursor

    movlw b'00001000' ;mode 4 bits
    movwf port_lcd
    call e_pulse
    call busy

;Entry Mode Set

   movlw b'00000000'
   movwf port_lcd
   call e_pulse
   movlw b'00000110'
   movwf port_lcd
   call e_pulse
   call busy

;---------------------------------------------------------------------------
;                     50 us
;---------------------------------------------------------------------------
 
busy ; 50us
    movlw 6 
    movwf temp_busy

attd_boucle
    nop
    nop
    nop
    decfsz temp_busy,F
    goto attd_boucle
    return
 

In your project you are using only 2 wires to connect to LCD. It is not actually SPI. SPI needs 3 wires. In your project 74HC595 which is a shift register is used. See the asm code I have posted. Most of that code is correct. Only some errors related to asm usage doesn't allow it to compile. Maybe betwixt can fix it or he can give you better code.

Use this tool to create delay codes.

**broken link removed**
 

His is what I try to do for the LCD is it correct? and I do not understand the difference between LCD and LCD-SPI, How to code a LCD-SPI?



Code:
; LCD TRIS
Ban1                          ;lcd RW leg is grounded, so we'll only write data to the lcd, and never read.

    movlw b'11000000'
    movwf tris_lcd    ;all output ports 

LCD_int

 ;use both lines of the display
    movlw b'00000010' ;mode 4 bits
    movwf port_lcd
    call e_pulse
    movlw b'00000010' ;mode 4 bits
    movwf port_lcd
    call e_pulse

;allow display and hide the cursor

    movlw b'00001000' ;mode 4 bits
    movwf port_lcd
    call e_pulse
    call busy

;Entry Mode Set

   movlw b'00000000'
   movwf port_lcd
   call e_pulse
   movlw b'00000110'
   movwf port_lcd
   call e_pulse
   call busy

;---------------------------------------------------------------------------
;                     50 us
;---------------------------------------------------------------------------
 
busy ; 50us
    movlw 6 
    movwf temp_busy

attd_boucle
    nop
    nop
    nop
    decfsz temp_busy,F
    goto attd_boucle
    return

betwixt is that correct?
 

The code you have posted is for parallel interface of LCD. In your project you can't use parallel interface. You are using serial interface with 74HC595. The LCD in 2 wire serial interface works in 4 bit mode. You have to send data to LCD serially and also the control signals.
 

paulfjujo made this code but it is in C and Since yesterday I try to transform its assembly language but I Boque serious !! It's like magic I don't understand
 

Attachments

  • SerialLcdTest.zip
    7 KB · Views: 28

His is what I try to do for the LCD is it correct? and I do not understand the difference between LCD and LCD-SPI, How to code a LCD-SPI?

In your project you are using only 2 wires to connect to LCD.

I reviewed the thread and don't see any schematic posted by thierryneuch himself. All interface circuits have been suggested by others. How do you know which circuit he's presently using?

Before the thread is descending into chaos, the matter of debate should be clarified.
 

Unforunately the code in post #73 is for PIC18F series processors which are significantly different to the PIC10 being used. The code will not translate easily.
Thierry, you need to understand the principles of driving an LCD before going further. I will again try to explain:

The LCD module typically has 16 pins which connect to an internal processor, generically called HD44780.

There are two pins for the backlight LED which we can ignore.
There are 8 data pins, these are the pins used to carry information for configuation and what characters to display.
There are three control pins:
'E' is the Enable pin, it turns the LCD on to receive data/commands when low and tells it to action the data/commands when taken high.
R/-W is the Read/Write pin, when low, the HD44780 accepts data/commands, when high the internal status of the HD44780 can be read back.
RS is the register select pin, when low it directs information on the data pins to the configuration registers, when high the information is to be displayed.
The other pins are for the supply voltage and contrast setting voltage.

'Data' is the numeric code for the character to print, 'Commands' are for things like telling it how many lines to display, positioning the cursor, making it flash and so on.

They can be used in two different ways called '8-bit mode' and '4-bit mode'. From the viewers perspective, there is no difference but electrically, the lower 4 bits of the data bus are ignored and the 8-bit data the LCD needs is sent as two halves on the upper data pins. So instead of bits 7-0 being sent in one step, bits 7-4 are sent first then bits 3-0 are sent second. This is done to save connections to the LCD, it's a little slower but normally not noticed.

It would be useful for you to download the data sheet for the HD44780 to learn more about how it works.

The problem in your application is you need to send all those LCD bits but there are only two pins on the PIC to do it. There is a way to send any amount of bits using only two wires, it is called 'serial', meaning 'one after another'. You need another device in the circuit to read the bits as they arrive one-by-one and convert them back to parallel (all present at once). The method is to use one pin as the 'clock' and the other to carry the 'Data'. You make the data pin high if the bit is '1' and low if it is '0' so the pin holds the state of the first bit in the number you are sending. Then you change the state of the clock pin, then you change the clock back again. The serial to parallel converter sees the change in clock state and moves the data bit into a 'shift register'. This process is repeated 8 times, once for each of the data bits. The shift register then holds all the 8 bits it has collected and they can be read out in parallel on 8 pins. There is a complication though! How does the shift register know which bit is which? Although it has received 8 clock pulses and shifted 8 bits in to itself, it may have started on bit 5 of one lot of data and finished on bit 4 of the next, there is nothing to tell it where each block of bits starts from. This is what the third signal on an SPI bus does, when low it alerts the SPI device that a transfer is about to start and when it goes high again, it tells the device that all the bits have been sent and it is safe to use them.

Your PIC does not have enough pins to produce that third signal so you can not use SPI. 'Clock' and 'Data' are already using the only pins you have. So a slightly different trick is used, it is not SPI but similar. You can ignore the LCD signal called R/-W because you are never going to read the HD44780 status, just trust it is correct, that reduces the number of signals to the LCD to six, D7, D6, D5, D4, RS and E. The spare bits can be used to reset the shift register, they become 'markers' to show where the data starts and stops.

Brian.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top