|
|
View previous topic :: View next topic |
Author |
Message |
eyewonder300
Joined: 09 Jun 2004 Posts: 52
|
Need help with TRIS on Port C, PIC16F76 |
Posted: Sat Nov 29, 2014 4:03 pm |
|
|
I'm getting frustrated with not knowing how to toggle bits on Port C. Sure seems like a simple thing, but I can not make it work on Port C, but it DOES work on Port A.
Each Port A pin drives a FET, which turns on an LED.
All Port C pins have 10k pull-up to Vcc.
This test program will just turn on all LEDs, and drive low the even numbered Port C pins, and hold it for ~1 sec (so that I can scope out what's working & what's not), then it will turn off all the LEDs, and drive high the even numbered Port C pins.
Logic probe shows the even numbered Port C pins remain low all the time, the odd numbered ports are all high, but the LEDs driven by Port A are toggling, as expected
Compiler is 4.069
Using USB ICD-U40
Here is the simple prog & headers.
Cheers,
Steve
Code: |
#include "X:\CCS_Projects\CAT5_Cable_Tester\NET_TST.h"
void main()
{
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_spi(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
set_tris_A(0x00); // All bits OUTPUTS, to drive LEDs
set_tris_c(0b10101010); //bits 0, 2, 4, 6 as outputs, bits 1, 3, 5, 7 inputs
while (1==1)
{
Failed_LED_On; // Port A.0 drives a FET, turning on LED
Straight_LED_On; // ""
Crossed_LED_On; // ""
Unplugged_LED_On; // ""
output_bit(white_green,0); // ALL Port C pins have 10k pullups
output_bit(white_orange,0);
output_bit(white_blue,0);
output_bit(white_brown,0);
delay_ms(100);
Failed_LED_Off;
Straight_LED_Off;
Crossed_LED_Off;
Unplugged_LED_Off;
output_bit(white_green,1);
output_bit(white_orange,1);
output_bit(white_blue,1);
output_bit(white_brown,1);
delay_ms(100);
}
}
|
Code: |
#include <16F76.h>
#device *=16
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES PUT //Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES BROWNOUT //Reset when brownout detected
#use delay(clock=10000000,RESTART_WDT)
//--------- Port register defines/usage
// Port A bits turn on the status LED's
#bit Unplugged_LED = 5.0 //Port A, bit 0
#bit Failed_LED = 5.1 //Port A, bit 1
#bit Straight_LED = 5.2 //Port A, bit 2
#bit Crossed_LED = 5.3 //Port A, bit 3
#define Failed_LED_On Failed_LED = 1
#define Failed_LED_Off Failed_LED = 0
#define Straight_LED_On Straight_LED = 1
#define Straight_LED_Off Straight_LED = 0
#define Crossed_LED_On Crossed_LED = 1
#define Crossed_LED_Off Crossed_LED = 0
#define Unplugged_LED_On Unplugged_LED = 1
#define Unplugged_LED_Off Unplugged_LED = 0
// Port C bits used to both drive & read lines of cable
// All lines have 47k-ohm pull-up resistors
#byte Cable_Data = 7 //Port C
#bit White_Green = 7.0 //Port C, bit 0
#bit Green = 7.1 //Port C, bit 1
#bit White_Orange = 7.2 //Port C, bit 2
#bit Blue = 7.3 //Port C, bit 3
#bit White_Blue = 7.4 //Port C, bit 4
#bit Orange = 7.5 //Port C, bit 5
#bit White_Brown = 7.6 //Port C, bit 6
#bit Brown = 7.7 //Port C, bit 7
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Nov 29, 2014 9:08 pm |
|
|
Quote: | #bit White_Green = 7.0 //Port C, bit 0
output_bit(white_green, 0);
|
You are giving the output_bit() function an invalid value for the first
parameter. It must be a CCS pin number.
Here is the CCS manual section:
Quote: | output_bit( )
Syntax:
output_bit (pin, value)
Parameters: Pins are defined in the devices .h file. The actual number is a bit address. For example, port a (byte 5 ) bit 3 would have a value of 5*8+3 or 43 . This is defined as follows: #define PIN_A3 43 . The PIN could also be a variable. The variable must have a value equal to one of the constants (like PIN_A1) to work properly. The tristate register is updated unless the FAST_IO mode is set on port A. Note that doing I/O with a variable instead of a constant will take much longer time. |
|
|
|
eyewonder300
Joined: 09 Jun 2004 Posts: 52
|
Success |
Posted: Sun Nov 30, 2014 8:13 am |
|
|
Thanks PCM. As expected it was a simple answer - once I recognized it.
Cheers,
Steve |
|
|
muhibraza1
Joined: 26 Jul 2013 Posts: 23
|
|
Posted: Tue Dec 02, 2014 12:29 am |
|
|
Also consider the read-modify-write problem.
here's the reference manual for I/O ports :
http://ww1.microchip.com/downloads/en/DeviceDoc/31009a.pdf
take a look on the I/O Programming Considerations, Initialization and Design Tips sections. _________________ PCWHD Compiler v4.124
ICD U-64 Hardware Rev 2 & 3
CCSLOAD 4.053 |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Tue Dec 02, 2014 4:16 am |
|
|
I assume you're familiar with some other version of C for the PICs or with assembler. CCS C has a much simpler syntax and provides much more support than most other PIC Cs. Due to this, there are a number of points to think about:
CCS C provides port direction management by default. TRIS won't work out of the box, you have to use fast_io. As you don't specify fast_io in your code, your set_tris_x() calls are redundant and won't do anything. They should be simply deleted. The direction of each IO pin will automatically be set when they are used.
In general, try not to think "how do I translate what I used to do into CCS?", but instead try to learn the CCS way. Its far simpler and easy to learn, but you need to drop some "old ways".
As you've been told, you should be using the CCS defined pin constants:
Code: |
//--------- I/O Pin defines/usage
// Port A bits turn on the status LED's
#define Unplugged_LED PIN_A0
#define Failed_LED PIN_A1
#define Straight_LED PIN_A2 //Port A, bit 2
#define Crossed_LED PIN_A3 //Port A, bit 3
|
Port register addresses change from device to device. Using the CCS pin defines is more portable than specifying addresses. If you really want to use a port address and #bit then use getenv(), which also comparitively portable. #bit is rarely used for port IO in CCS C.
output_bit() is rarely used and is slow. Its only used when the bit value really has to be a variable. Instead, whenever the value is a constant, as in your posted code, use output_low() or output_high() as appropriate. Even when the value is a variable its often better to use an if to select the relevant constant version:
Code: |
if (Bit_Value)
{
output_high(Failed_LED);
}
else
{
output_low(Failed_LED);
}
|
CCS C provides defines for TRUE and FALSE, and a boolean type. It's generally more readable to use these in place of 1 and 0.
Using defines to replace C code is usually considered a "obfuscation" tactic as it makes the code more difficult to understand. Where the idea is to abstract the function from the implementation - for example to simplify inverted logic and sequences of statement to achieve one action, e.g. setting SPI DACs to a voltage - then personally I prefer to use abstraction routines: simple routines, possibly defined as in-line. Doing it in macros (defines) is often not a great idea.
The 16F76 is one of the oldest PICs still generally available. There are plenty of newer ones with much better performance, more peripherals and memory and at lower cost. The 16F76 is fine if its all you've got, but there are other, far better PICs out there. |
|
|
|
|
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
|