News:

PROTON pic BASIC Compilers for PIC, PIC24, dsPIC33

Main Menu

16F17146 not working correctly

Started by Fanie, Jun 10, 2025, 03:06 PM

Previous topic - Next topic

Fanie

I have a question.

Does EEPROM have a special property to be used instead of flash ?

Why not simply write and read flash using Cread and Cwrite ?

It should be without the delays ?  Never used it so I'm asking.

trastikata

Quote from: Fanie on Jun 11, 2025, 04:10 PMI have a question...

- Neither FLASH nor EEPROM requires delay for reading.
- Both require delays after writing.
- EEPROM can be overwritten directly without the need of erasure.
- FLASH needs to be erased before being able to write in it.
- EEPROM can be written in single bytes.
- FLASH, most of the time, has to be written in pages.
- FLASH is erased in blocks, often different size from the write page size.
- Usually EEPROM has endurance of 100k writes.
- FLASH can endure about 10k writes.

Interesting facts - FLASH being erased means all cells are set to "1s" not zeroes. You can clear the bits in a FLASH byte from "1s" to "0s" without erasing it, but can't do the same in reverse from "0s" to "1s" without erasure.

trastikata

Quote from: Fanie on Jun 11, 2025, 07:55 AMI have never encountered a problem writing to eeprom, it's the reading that requires a delay. It won't do anything if you add the delay (thousands of NOP's), but it can cause unwanted delays in a fast app.  The newer pic's should (assumption) read and write faster to eeprom than the old ones, will test when I get the 16F17146 going.

TRISA = %00010001               ' Configure I/O
ANSELA = %00000001               ' Select analog input pin ADin 0
TRISB = %00000000
TRISC = %00001000
ODCONC = %00000000               ' output souce and sink current

Hello Fanie,

as people advised, in PIC16F17146 there more ADC-related registers than in old devices and their default POR settings must be consulted in the datasheet, for example:

- You ignore setting ADCON0 but its bit 1 is set by default - this means the ADC is operating in Differential mode by default.
- ADC Results Format is by default left justified, two's complement, zero-filled

Fanie

#23
I did set the A/D control registers

TRISA = %00010001               ' Configure I/O
ANSELA = %00000001               ' Select analog input pin ADin 0
TRISB = %00000000
TRISC = %00000000
ODCONC = %00000000               ' output souce and sink current
ADCON0 = %10000001              ' Set analogue inputs on
ADCON1 = %01010000              ' AD control reg

PMD0 = %00100000                 '  Peripheral Modules
PMD1 = %11111111                 '  Peripheral Modules Disable
PMD2 = %11111111                 '  Peripheral Modules Disable
PMD3 = %11111111                 '  Peripheral Modules Disable
PMD4 = %11111110                 '  Peripheral Modules Analog-to-Digital Converter enabled

CCP1CON = 0                     ' And disable CCP

The A/D works fine


If I program with DvdR given a fixed value then it works immediately.

When I program with the self calibration code included which determine the value for DvdR, it seems the pic hangs up and does not work.  The wife called to go eat so I left it on, and when I came back, the calibration code completed and it shows the correct value.

I did this three times, and it takes some hours to complete the calibration routine.  No idea why.
I have something else to do now and will be back later to try to find the delay.

If I start the pic with power-up it reads the EEPROM correctly and display the correct value.

top204

Altering the PMD bits can make a big difference to the current drawn by a device, especially when Sleep mode is used. However, if they are setup incorrectly, they can cause problems, because some peripherals will not work.

So for projects, I always make a set of $defines for the bit masks and then 'Or' them together in the setup procedure of a program, so it is clear to see what peripherals have been disabled, and can easily be altered to suit. For example, the code listing below is for the PIC16F17146 device operating at 32MHz with its internal oscillator, and it disables all the peripherals it can. Which is not practical in the real world, but it shows how to do it, and if a peripheral is required, simply remove it from the list of 'Or'ed constant names in the Setup procedure:

'
'   /\\\\\\\\\
'  /\\\///////\\\
'  \/\\\     \/\\\                                                 /\\\          /\\\
'   \/\\\\\\\\\\\/        /\\\\\     /\\\\\\\\\\     /\\\\\\\\   /\\\\\\\\\\\  /\\\\\\\\\\\  /\\\\\\\\\
'    \/\\\//////\\\      /\\\///\\\  \/\\\//////    /\\\/////\\\ \////\\\////  \////\\\////  \////////\\\
'     \/\\\    \//\\\    /\\\  \//\\\ \/\\\\\\\\\\  /\\\\\\\\\\\     \/\\\         \/\\\        /\\\\\\\\\\
'      \/\\\     \//\\\  \//\\\  /\\\  \////////\\\ \//\\///////      \/\\\ /\\     \/\\\ /\\   /\\\/////\\\
'       \/\\\      \//\\\  \///\\\\\/    /\\\\\\\\\\  \//\\\\\\\\\\    \//\\\\\      \//\\\\\   \//\\\\\\\\/\\
'        \///        \///     \/////     \//////////    \//////////      \/////        \/////     \////////\//
'                                  Let's find out together what makes a PIC Tick!
'
' Code listing template for an Internal Oscillator operating at 32MHz on a PIC16F17146 device.
' Written by Les Johnson for the Positron8 BASIC Compiler.
'
    Device = 16F17146                                               ' Tell the compiler what device to compile for
    Declare Xtal = 32                                               ' Tell the compiler what frequency the device is operating at (in MHz)
    Declare Float_Display_Type = Fast                               ' Use the compiler's faster floating point display routine
    Declare Auto_Heap_Arrays = On                                   ' Make all arrays "Heap" types, so they always get placed after standard variables
    Declare Auto_Heap_Strings = On                                  ' Make all Strings "Heap" types, so they always get placed after standard variables
    Declare Auto_Variable_Bank_Cross = On                           ' Make sure all multi-byte variables remain within a single RAM bank
'
' Setup USART1
'
    Declare Hserial_Baud = 9600                                     ' Set the Baud rate for USART1
    Declare HRSOut1_Pin  = PORTC.4                                  ' Tell the compiler to setup pin PORTC.4 for USART1 Tx
    Declare HRSIn1_Pin   = PORTC.5                                  ' Tell the compiler to setup pin PORTC.5 for USART1 Rx
'
' Peripheral disabling bit masks to be ORed into the PMDx SFRs for a PIC16F17146 device
'
' PMD0 Bit masks
'
$define cNVM_Off   %00000001                                        ' Disable NVMMD NVM Module
$define cCRC_Off   %00000010                                        ' Disable CRC Engine
$define cSCAN_Off  %00000100                                        ' Disable NVM Memory Scanner
$define cSYSC_Off  %00001000                                        ' Disable Peripheral System Clock Network
$define cACT_Off   %00010000                                        ' Disable Active Clock Tuning
$define cIOC_Off   %00100000                                        ' Disable Interrupt-on-Change (all ports)
$define cCLKR_Off  %01000000                                        ' Disable Clock Reference
$define cTMR0_Off  %10000000                                        ' Disable Timer0
'
' PMD1 Bits masks
'
$define cTMR1_Off  %00000001                                        ' Disable Timer1
$define cTMR3_Off  %00000010                                        ' Disable Timer3
$define cTMR2_Off  %00000100                                        ' Disable Timer2
$define cTMR4_Off  %00001000                                        ' Disable Timer4
$define cCCP1_Off  %00100000                                        ' Disable CCP1
$define cCCP2_Off  %01000000                                        ' Disable CCP2
$define cPWM1_Off  %11000000                                        ' Disable PWM1
'
' PMD2 Bit masks
'
$define cPWM2_Off  %00000001                                        ' Disable PWM2
$define cNCO1_Off  %00001000                                        ' Disable NCO
$define cCWG1_Off  %00010000                                        ' Disable CWG1
$define cCLC1_Off  %00100000                                        ' Disable CLC1
$define cCLC2_Off  %01000000                                        ' Disable CLC2
$define cCLC3_Off  %10000000                                        ' Disable CLC3
'
' PMD3 Bit masks
'
$define cCLC4_Off  %00000001                                        ' Disable CLC4
$define cUART1_Off %00000010                                        ' Disable UART1
$define cUART2_Off %00000100                                        ' Disable UART2
$define cMSSP1_Off %00001000                                        ' Disable MSSP1
$define cMSSP2_Off %00010000                                        ' Disable MSSP2
$define cFVR_Off   %00100000                                        ' Disable Fixed Voltage Reference
$define cCM1_Off   %01000000                                        ' Disable Comparator 1
$define cCM2_Off   %10000000                                        ' Disable Comparator 2
'
' PMD4 Bit masks
'
$define cADC_Off   %00000001                                        ' Disable ADC
$define cDAC1_Off  %00000010                                        ' Disable DAC1
$define cDAC2_Off  %00000100                                        ' Disable DAC2
$define cOPA1_Off  %00001000                                        ' Disable Operational Amplifier
$define cZCD_Off   %00010000                                        ' Disable Zero-Cross Detect
'
' Global variables and constants can be placed here
'
'------------------------------------------------------------------------------------------
' The main program starts here
'
Main:
    Setup()                                                         ' Setup the program and any peripherals

    Do

    Loop

'------------------------------------------------------------------------------------------
'
'
' **** More user procedures can be placeed in this space ****
'
'
'------------------------------------------------------------------------------------------
' Setup the program and any peripherals
' Input     : None
' Outout    : None
' Notes     : None
'
Proc Setup()
    Osc_Init_32MHz()                                                ' Initialise the oscillator on a PIC16F17146 device to operate at 32MHz
'
' Set the PMD registers to reduce power consumption by disabling unused peripherals
'
    PMD0 = cNVM_Off | cCRC_Off | cSCAN_Off | cSYSC_Off | cACT_Off | cIOC_Off | cCLKR_Off | cTMR0_Off        ' Disable NVMMD, CRC, NVM, Periph System Clock, Active Clock Tuning, IOC, Clock Ref, and Timer0
    PMD1 = cTMR1_Off | cTMR3_Off | cTMR2_Off | cTMR4_Off | cCCP1_Off | cCCP2_Off | cPWM1_Off                ' Disable Timer1, Timer2, Timer3, Timer4, CCP1, CCP2, and PWM1
    PMD2 = cPWM2_Off | cNCO1_Off | cCWG1_Off | cCLC1_Off | cCLC2_Off | cCLC3_Off                            ' Disable PWM2, NCO, CWG1, CLC1, CLC2, and CLC3
    PMD3 = cCLC4_Off | cUART1_Off | cUART2_Off | cMSSP1_Off | cMSSP2_Off | cFVR_Off | cCM1_Off | cCM2_Off   ' Disable CLC4, UART1, UART2, MSSP1, MSSP2, FVR, Comparator1, and Comparator2
    PMD4 = cADC_Off | cDAC1_Off | cDAC2_Off | cOPA1_Off | cZCD_Off                                          ' Disable ADC, DAC1, DAC2, Op-Amp, and ZCD
'
' More setups here when required
'
EndProc

'------------------------------------------------------------------------------------------
' Initialise the oscillator on a PIC16F17146 device for 16MHz
' Input     : None
' Outout    : None
' Notes     : For internal oscillator config settings
'
Proc Osc_Init_16MHz()
    OSCCON1 = %01100010                                             ' NDIV is 4. HFINTOSC
    OSCCON3 = %00000000
    OSCEN   = %00000000
    OSCFRQ  = %00000100                                             ' HFFRQ is 16MHz
    OSCTUNE = %00000000
    ACTCON  = %00000000
    DelayMs 100                                                     ' Wait for stability
EndProc

'------------------------------------------------------------------------------------------
' Initialise the oscillator on a PIC16F17146 device for 32MHz
' Input     : None
' Outout    : None
' Notes     : For internal oscillator config settings
'
Proc Osc_Init_32MHz()
    OSCCON1 = %01100010                                             ' NDIV is 4. HFINTOSC
    OSCCON3 = %00000000
    OSCEN   = %00000000
    OSCFRQ  = %00000101                                             ' HFFRQ is 32MHz
    OSCTUNE = %00000000
    ACTCON  = %00000000
    DelayMs 100                                                     ' Wait for stability
EndProc

'------------------------------------------------------------------------------------------
' Setup the config fuses for an internal oscillator on a PIC16F17146 device
' OSC pins are general purpose I/O lines
'
    Config1 FEXTOSC_OFF,_                                           ' External Oscillator disabled
            RSTOSC_HFINTOSC_16MHz,_                                 ' Reset Oscillator Selection is HFINTOSC (16MHz)
            CLKOUTEN_OFF,_                                          ' CLKOUT function is disabled
            CSWEN_ON,_                                              ' Writing to NOSC and NDIV is allowed
            VDDAR_HI,_                                              ' Internal analogue systems are calibrated for operation between VDD = 2.3 - 5.5V
            FCMEN_ON                                                ' Fail-Safe Clock Monitor enabled

    Config2 MCLRE_EXTMCLR,_                                         ' RA3 pin function is MCLR
            PWRTS_PWRT_OFF,_                                        ' Power-up Timer is disabled
            LPBOREN_OFF,_                                           ' Low-Power BOR disabled
            BOREN_OFF,_                                             ' Brown-out Reset disabled
            DACAUTOEN_OFF,_                                         ' DAC Buffer reference range is determined by the REFRNG bit
            BORV_LO,_                                               ' Brown-out Reset Voltage (VBOR) set to 1.9V
            ZCD_OFF,_                                               ' ZCD can be enabled by setting the ZCDSEN bit of ZCDCON
            PPS1WAY_OFF,_                                           ' The PPSLOCKED bit can be set and cleared as needed (unlocking sequence is required)
            STVREN_ON                                               ' Stack Overflow or Underflow will cause a reset

    Config3 WDTCPS_WDTCPS_31,_                                      ' WDT Period Divider ratio is 1:65536. Software control of WDTPS
            WDTE_OFF,_                                              ' WDT Disabled. SEN is ignored
            WDTCWS_WDTCWS_7,_                                       ' WDT Window always open 100%
            WDTCCS_SC                                               ' WDT Input Clock is software control

    Config4 BBSIZE_BB512,_                                          ' 512 words boot block size
            BBEN_OFF,_                                              ' Boot Block disabled
            SAFEN_OFF,_                                             ' Storage Area Flash disabled
            WRTAPP_OFF,_                                            ' Application Block is Not write protected
            WRTB_OFF,_                                              ' Boot Block is Not write protected
            WRTC_OFF,_                                              ' Configuration Register is Not write protected
            WRTD_OFF,_                                              ' Data EEPROM is Not write protected
            WRTSAF_OFF,_                                            ' Storage Area Flash is Not write protected
            LVP_OFF                                                 ' Low Voltage Programming disabled

    Config5 CP_OFF,_                                                ' Program Flash Memory code protection is disabled
            CPD_OFF                                                 ' Data EEPROM code protection is disabled

It takes a bit of time to create the $defines from the datasheet, because 'as usual with microchip', each device has different bit placements, but In My Opinion, clarity within a program is always a "must have", for any future changes required to it.

Also, for the newer devices, it is 'always' better to create a procedure that sets up the ADC peripheral, because they are a lot more complex than the original setups that the Declares cater for, and the default settings are not always what is required, and it is not the compiler's fault.

A read of the device datasheet's ADC section, and the registers associated with it, are a "must read" for the newer devices.

For larger projects, it is sometimes better to make an include file that contains project's and device details for the compiler, and any Declares, $defines, and multiple used variables, Symbols, and Procedures etc... I normally call the file: "Program Name Acronym_Header.inc", for example, a main program named "My_Project.bas", would use a header file named: "MP_Header.inc". The header file gets placed near the beginning of the main program listing, as an Include. It makes the code listing a lot easier to read and understand, and easier to change, when required.

Fanie

#25
Thank you again Les !

In this line -
  Config3 WDTCPS_WDTCPS_31,_     ' WDT Period Divider ratio is 1:65536. Software control of WDTPS

Where does the 31 comes from ?
All I can see is the FIN = 31kHz and 31 DEC = %11111 ?

top204

#26
It is a name that microchip gave within its information files, and so was used for the fuse names.

It is the number for the division ratio for the watchdog timer. See at the bottom of the device's ".ppi" file:

; CONFIG3 Options
; WDT Period Select bits
WDTCPS_WDTCPS_0 EQU 0x3FE0                     ; Divider ratio 1:32
WDTCPS_WDTCPS_1 EQU 0x3FE1                     ; Divider ratio 1:64
WDTCPS_WDTCPS_2 EQU 0x3FE2                     ; Divider ratio 1:128
WDTCPS_WDTCPS_3 EQU 0x3FE3                     ; Divider ratio 1:256
WDTCPS_WDTCPS_4 EQU 0x3FE4                     ; Divider ratio 1:512
WDTCPS_WDTCPS_5 EQU 0x3FE5                     ; Divider ratio 1:1024
WDTCPS_WDTCPS_6 EQU 0x3FE6                     ; Divider ratio 1:2048
WDTCPS_WDTCPS_7 EQU 0x3FE7                     ; Divider ratio 1:4096
WDTCPS_WDTCPS_8 EQU 0x3FE8                     ; Divider ratio 1:8192
WDTCPS_WDTCPS_9 EQU 0x3FE9                     ; Divider ratio 1:16384
WDTCPS_WDTCPS_10 EQU 0x3FEA                    ; Divider ratio 1:32768
WDTCPS_WDTCPS_11 EQU 0x3FEB                    ; Divider ratio 1:65536
WDTCPS_WDTCPS_12 EQU 0x3FEC                    ; Divider ratio 1:131072
WDTCPS_WDTCPS_13 EQU 0x3FED                    ; Divider ratio 1:262144
WDTCPS_WDTCPS_14 EQU 0x3FEE                    ; Divider ratio 1:524299
WDTCPS_WDTCPS_15 EQU 0x3FEF                    ; Divider ratio 1:1048576
WDTCPS_WDTCPS_16 EQU 0x3FF0                    ; Divider ratio 1:2097152
WDTCPS_WDTCPS_17 EQU 0x3FF1                    ; Divider ratio 1:4194304
WDTCPS_WDTCPS_18 EQU 0x3FF2                    ; Divider ratio 1:8388608
WDTCPS_WDTCPS_19 EQU 0x3FF3                    ; Divider ratio 1:32
WDTCPS_WDTCPS_20 EQU 0x3FF4                    ; Divider ratio 1:32
WDTCPS_WDTCPS_21 EQU 0x3FF5                    ; Divider ratio 1:32
WDTCPS_WDTCPS_22 EQU 0x3FF6                    ; Divider ratio 1:32
WDTCPS_WDTCPS_23 EQU 0x3FF7                    ; Divider ratio 1:32
WDTCPS_WDTCPS_24 EQU 0x3FF8                    ; Divider ratio 1:32
WDTCPS_WDTCPS_25 EQU 0x3FF9                    ; Divider ratio 1:32
WDTCPS_WDTCPS_26 EQU 0x3FFA                    ; Divider ratio 1:32
WDTCPS_WDTCPS_27 EQU 0x3FFB                    ; Divider ratio 1:32
WDTCPS_WDTCPS_28 EQU 0x3FFC                    ; Divider ratio 1:32
WDTCPS_WDTCPS_29 EQU 0x3FFD                    ; Divider ratio 1:32
WDTCPS_WDTCPS_30 EQU 0x3FFE                    ; Divider ratio 1:32
WDTCPS_WDTCPS_31 EQU 0x3FFF                    ; Divider ratio 1:65536, software control of WDTPS

So, as far as I can tell, the watchdog ratio is 1:65536, and is also controllable by software when the 31 divisor is used.

For a more fixed ratio, the "WDTCPS_WDTCPS_2" setting can be used, which will set the watchdog ratio (if enabled) to 1:128, and is the compiler's default setting.

Fanie

I have everything working now.  The eeprom writes and reads perfectly and the A/D works correctly.

Thank you all for your contributions, I have a pic for my boards.

While I was joking about filling the "huge" program memory (like replacing the delays with many NOP's), if you create text or graphics for a display it can gulp up the flash in no time.  (That is why the Chinese displays allow .JPG files you create to show various displays and control buttons, slides etc and the micro operates only the controls in it.)

On the humor side, I managed to break the PDS editor, returning a comment - redefining symbol that cannot be redefined ;D
I waited a while, but nothing happened  ::)  when I used
asm
(with already defined registers given a value)
endasm