MAX6675 with PIC18F45k22 Data transmission via UART Problem - c

I am using MPLAB XC8 to program pic18f45k22 to read data from 2 thermocouples. The code showed 2 problems, The first is that during simulation, the data from the sensor is shifted (sent to the second address)
for Example: if I have 2 addresses 0x0D and 0x0F, and 2 values 100 and 95, and 100 should got to 0x0D and 95 to 0x0F. However 100 goes to 0x0F and 95 to 0x0D.
**The second ** appears after uploading the code to the MCU, and it is that the MCU cannot Read any data from the sensors.
this is the main code:
void main(void) {
//SPI configuration
spiInit();
ANSELB = 0x00; //PORTB bits as digital
TRISB3 = 0; //GPIO as CS output
TRISB4 = 0;
TRISB5 = 0;
LATBbits.LATB3 = 1;
LATBbits.LATB4 = 1;
LATBbits.LATB5 = 1;
timer1init(); //initiate timer1
uartinit(9600); //initiate UART
__delay_ms(100);
while(1){
switch (cnt){ //timer interrupt routine every 1 second
//thermocouple code
case 50:
LATB3 = 0; //turn on CS
thercoup1 = spiRead(0)<<8; //Read first byte
thercoup1 |= spiRead(0); //add second byte with first one
LATB3 = 1; //turn off CS1
thercoup1 = (thercoup1>>4);
//thercoup1 = (thercoup1>>3)*0.25; //another method for calculating thermocouple value
LATB4 = 0; //turn on CS1
thercoup2 = spiRead(0)<<8; //Read first byte
thercoup2 |= spiRead(0); //add second byte with first one
LATB4 = 1; //turn off CS1
thercoup2 = (thercoup2>>4); //right shift of the reading
HMT_WriteVPN16(0x08000C, thercoup1); //send thermocouple1 data to 0x08000C
HMT_WriteVPN16(0x08000E, thercoup2); //send thermocouple2 data to 0x08000E
cnt = 0; //reset timer
break;
}
}
}
void __interrupt() ISR (void){
timer();
UART_Read();
}
And This is the configuration code of SPI module.
void spiInit(void)
{
ANSELC = 0x00;
SSP1STATbits.SMP = 0; //input Data is sampled at the middle
SSP1STATbits.CKE = 0; //Transmission occurs from Idle to Active
//Master mode Fosc/4
SSP1CON1bits.SSPM0 = 0;
SSP1CON1bits.SSPM1 = 0;
SSP1CON1bits.SSPM2 = 0;
SSP1CON1bits.SSPM3 = 0;
//
SSP1CON1bits.CKP = 1; //clock polarity is high
SSP1CON1bits.SSPEN = 1;//Serial communication is Enabled
SSP1CON1bits.SSPOV = 0;//Overflow is off
SSP1CON1bits.WCOL = 0;//Write collision is off
TRISCbits.RC5 = 1; //SDO is Disabled
TRISCbits.RC4 = 1; //SDI is Enabled
TRISCbits.RC3 = 0; //SCK is Enabled
}
unsigned short spiRead(unsigned char dat) //REad the received data
{
SSPBUF= dat; //the data loaded on the SSPBUF are not important.
while(!SSPSTATbits.BF); //save the received data from the slave.
return(SSPBUF);
}

Related

UART only receiving FF and FE

I am currently working on transmitting from a PIC18F4620, through a FT232, to CoolTerm. I am currently only receiving FF and FE from the PIC though. I was wondering why this may be the case. The Rx - TX are correctly switched, the cable connecting them appears to be secure. The only issue I can think of is the baud rate would be incorrect, But looking at the datasheet I don't believe it is. any insight would be greatly appreciated. (I arbitrarily chose 51 as my test number. any number or letter would work).
Circuit
const unsigned char MSG0[] = "Transmitting... ";
const unsigned char MSG1[] = "Sent:";
const unsigned char MSG2[] = "TEST:";
// Subroutine Declarationsb
#include <pic18.h>
// Subroutines
#include "lcd_portd.c"
#include <delays.h>
#include <plib.h>
#include <stdint.h>
void UART_TX_Init(void)
{
BRG16 = 0;
BRGH = 1; // Set For High-Speed Baud Rate
SPBRG = 64; // Set The Baud Rate To Be 9600 bps
//--[ Enable The Ascynchronous Serial Port ]--
SYNC = 0;
SPEN = 1;
//--[ Set The RX-TX Pins to be in UART mode (not io) ]--
TRISC6 = 1; // As stated in the datasheet
TRISC7 = 1; // As stated in the datasheet
TXEN = 1; // Enable UART Transmission
}
void UART_Writes(uint8_t data)
{
while(!TRMT);
TXREG = data;
}
// Main Routine
void main(void)
{
UART_TX_Init();
unsigned int result = 0;
unsigned int i;
uint8_t data = 51;
TRISA = 0;
TRISC = 0;
TRISB = 0;
TRISD = 0;
TRISE = 0;
TRISA = 0;
TRISB = 0x00;
PORTC = 0;
PORTD = 0;
PORTE = 0;
ADCON1 = 0x0F;
LCD_Init(); // initialize the LCD
LCD_Move(0,0); for (i=0; i<20; i++) LCD_Write(MSG0[i]);
Wait_ms(100);
LCD_Move(1,0); for (i=0; i<5; i++) LCD_Write(MSG1[i]);
while(1) {
Wait_ms(1000);
UART_Writes(data);
LCD_Move(1,5); LCD_Out(data,3,0);
}
}
CoolTerm
What is your clock frequency and how did you configured your crystal oscillator setup ? please share your clock setting and configuration.
If clock setting is fine then calculate the correct baud-rate and try.
void UART_Writes(uint8_t data)
{
while(!TRMT)
{
//put Nop() and try
}
TXREG = data;
}

PIC24 Evaluation Board always returns 1 when reading input from pins [resolved]

I am trying to set up a function which will read digital input from pins on a PIC24 MCU and use the bits that are read to reconstruct a full value. The MCU can properly receive and send values over UART and output these to a parallel bus, but now I am trying to read into the bus and the pins will always read 1 regardless of whether or not a voltage is present at the pins. I cannot figure out why this is and would appreciate some help if anyone has any insight. These are the functions I am using:
void configureReadPins()
{
//configuring pins for bus
TRISAbits.TRISA9 = 1; //configure A9 as input
TRISCbits.TRISC3 = 1; //configure C3 as input
TRISCbits.TRISC4 = 1; //configure C4 as input
TRISCbits.TRISC5 = 1; //configure C5 as input
TRISBbits.TRISB5 = 1; //configure B5 as input
TRISBbits.TRISB6 = 1; //configure B6 as input
TRISBbits.TRISB7 = 1; //configure B7 as input
TRISBbits.TRISB8 = 1; //configure B8 as input
//Setting Read pin to output and Write pin to input
TRISBbits.TRISB12 = 0;
TRISBbits.TRISB13 = 1;
}
void readFromFPGA()
{
configureReadPins();
int i = 0;
int bitcount = 0;
int pin = 0;
int index = 0;
uint16_t addressRead = 0;
uint16_t sampleRead = 0;
uint16_t comparisonSample = 0;
//LATBbits.LATB12 = 1; //tell FPGA MCU is ready to read
//while(PORTAbits.RA1 != 1); //wait for FPGA to set clock pin high in order to start reading the contents of the bus
while (index < 1024 && (numSamples != readCounter))
{
comparisonSample = dataArray1[index];
//reading sample point
for (i = 0; i < 2; i++)
{
for (bitcount = 0; bitcount < 8; bitcount++)
{
switch (bitcount)
{
case 7:
pin = PORTAbits.RA9;
sampleRead += pin;
break;
case 6:
pin = PORTCbits.RC3;
sampleRead += pin;
break;
case 5:
pin = PORTCbits.RC4;
sampleRead += pin;
break;
case 4:
pin = PORTCbits.RC5;
sampleRead += pin;
break;
case 3:
pin = PORTBbits.RB5;
sampleRead += pin;
break;
case 2:
pin = PORTBbits.RB6;
sampleRead += pin;
break;
case 1:
pin = PORTBbits.RB7;
sampleRead += pin;
break;
case 0:
pin = PORTBbits.RB8;
sampleRead += PORTBbits.RB8;
break;
}
//reads in value from left to right in bits
//AKA case 0 will read RB8, which gives MSB value of 8 bits received
if (i == 0 || (i == 1 && bitcount != 7) )
sampleRead <<= 1; //shift next bit to left to get in proper place
pin = 0;
}
}
sampleRead = 0;
index++;
}
In all cases, the values of pin is set to 1 after reading from the MCU's pins. Any idea why this is happening?
edit: The problem was I left the pins floating. Since they weren't connected to ground, the transistors used for the pins kept the previous high voltage so the pins were not reading as expected. Once the pins expected to read 0 were connected to ground they read the expected value of 0.

PIC16F883 Led Blink

I need to program a PIC16F883 to blink / light up LED's at the same time. The oscillator is running at 3,2768, and I'm using TIMER0 to help me with the timing.
Right now, I have a prescaler set to 1:256, so I get an interrupt every 50ms, and I have a variable that is calculated from that, to display how many seconds has gone.
If the input is changed, the seconds variable is of course reset again.
Here is the assignment from my teacher:
If Input is 0 (Closed):
The Red And The Green LED should be turned on at the same time for 15 seconds. After this the green LED should be turned
off completely, and the red LED should blink every fifth second for 10 minutes
If input is 1 (Opened):
The red LED should be turned off completely, and the green LED should be turned on for 10 minutes, and after that
it should be turned off too.
My timer is working fine. I have tested that. The program runs fine too and keeps the 2 LED's turned off for 15 seconds, then turns them off, but my red LED isn't blinking. I have been sitting at my desk all day desperately trying to find the error in my code.
Picture of the print:
Here is my C Code. I am using MPLab and the HI-TECH C compiler :)
#include <pic.h>
//Variabler
int B = 0; //Definerer variablen B, used as a flag
int A = 0; //Definerer veriablen A, used as a flag
int E = 0;
int savedstatus = 1; //Definere variablen savedstatus used to check last status for input
int millicounter = 0; //Variabel to calculate seconds
int sec = 0; //Variabel holding seconds gone
int count = 0; //For counting seconds passed, used in input0 subroutine
int onesec = 0; //Used to counting seconds for blinking LED in input0 subroutine
int scount = 0;
//Variabler slut
void interrupt jesper(void)
{
T0IF = 0x00;
TMR0 = 96;
millicounter++;
if(millicounter == 20)
{
sec++;
millicounter = 0;
}
}
//Subrutines
void input0()
{
if(sec<=15 && E==0)
{
PORTA = 0x21;
}
else if(A==0)
{
scount = 0;
sec = 0;
count = sec;
A = 1;
E = 1;
}
else if(sec<=600 && sec>count)
{
count++;
if((scount+5)>=count)
{
if(B==0)
{
onesec = sec;
B = 1;
PORTA = 0x01;
}
else if(sec>onesec)
{
PORTA = 0x00;
B = 0;
scount = count;
scount;
}
else
{
PORTA = 0x01;
}
}
else
{
PORTA = 0x00;
}
}
else PORTA = 0x00;
}
void input1()
{
if(sec<=600)
{
PORTA = 0x20;
}
else
{
PORTA = 0x00;
}
}
//Subrutines over
int main(void)
{
TRISA = 0x00; //Sets all A-PORTS to output
TRISB = 0x01; //Sets all PORTB to output with the exception of BIT0
TRISC = 0x00; //Sets All PORTC to output
ANSEL = 0x00; //Disable Analog ports
ANSELH = 0x00; //Disable Analog ports
//Timer Config
PSA = 0x00;
PS0 = 0x01;
PS1 = 0x01;
PS2 = 0x01;
TMR0 = 0x60;
GIE = 0x01;
T0IE = 0x01;
T0IF = 0x00;
T0CS = 0x00;
//Timer Config Over
while(0x01)
{
if(savedstatus != RB0)
{
savedstatus = RB0;
sec = 0;
E = 0;
A = 0;
}
if(savedstatus == 1)
{
input1();
}
else
{
input0();
}
}
}
I really hope that you can help me here :)
Here is my flowchart for the subroutine input0 where my problem is. Btw some of my variables have different names in the code itself, but it shouldn't be hard to see.
Your main() calls input0() as often as possible. When input0() is in the flashing state it uses the conditional sec > count. I suspect that your intention is that input0() should only change the LED state at intervals of a second. But then on the else side of that conditional you turn both LEDs off. This else side is executing many times because main() is calling input0() so often. Try deleting the else condition where you turn the LEDs off.
void input0()
{
<snip>
else if(sec<=600 && sec>count)
{
<snip>
}
else PORTA = 0x00; // <-- delete this line so you're not always turning the LED off
}

An issue that might lay in the code which I don't see (using a ledstrip) Atmel Studio 6.1

I am using Atmel Studio 6.1 and this is the code that I use, beside this i also got another code called "ledstrip.h". Which basically is an 1 dimensional array.
This is something for my study.
I am trying to send 12 bytes through a 'ledstrip'
code:
#define SPI_SS_bm PIN4_bm
#define SPI_MOSI_bm PIN5_bm
#define SPI_MISO_bm PIN6_bm
#define SPI_SCK_bm PIN7_bm
#define MIN_VALUE 0.4
#define F_CPU 32000000UL
#define P 128
#define FOO 0
#include <avr/io.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include "ledstrip.h"
void spi_init(void);
uint8_t spi_transfer(uint8_t data);
const uint8_t *ptr = image;
uint8_t num[12];
int line;
int g;
int data;
int i;
void row (const uint8_t *j)
{
uint32_t row2 = 0;
for(g = 0; g < 4; g++)
{
for(int i = 0; i < 8; i++)
{
row2 = (row2 << 3) | pgm_read_byte(j);
j++;
}
num[3*g] = (uint8_t) (row2 >> 16); //put bytes in the right order
num[3*g+1] = (uint8_t) (row2 >> 8);
num[3*g+2] = (uint8_t) (row2);
}
}
void spi_initialisation(void)
{
PORTC.DIRSET = SPI_SCK_bm|SPI_MOSI_bm|SPI_SS_bm;
PORTC.DIRCLR = SPI_MISO_bm;
SPIC.CTRL = (!SPI_CLK2X_bm) | // no double clock speed
SPI_ENABLE_bm | // SPI enable
!SPI_DORD_bm | // data order, MSB first
SPI_MASTER_bm | // master
SPI_MODE_0_gc | // mode 0
SPI_PRESCALER_DIV4_gc; // Presc. 4 (#2 MHz,500kHz)
}
void spi_init(void)
{
PORTC.DIRSET = PIN7_bm|PIN5_bm|PIN4_bm; // 7: MOSI 5: SCK
PORTC.OUTCLR = PIN4_bm; // 4: latch enable
PORTD.DIRSET |= PIN3_bm|PIN1_bm; // 3: MOSI 1: SCK
USARTC1.BAUDCTRLA = 0; // baud rate FCPU/2
USARTC1.BAUDCTRLB = 0; //
USARTC1.CTRLC = USART_CMODE_MSPI_gc; // SPI mode
USARTC1.CTRLA = 0; // no interrupts
USARTC1.CTRLB = USART_TXEN_bm; // enable transmit
USARTD0.BAUDCTRLA = 0; // baud rate FCPU/2
USARTD0.BAUDCTRLB = 0; //
USARTD0.CTRLC = USART_CMODE_MSPI_gc; // SPI mode
USARTD0.CTRLA = 0; // no interrupts
USARTD0.CTRLB = USART_TXEN_bm; // enable transmit
}
void init_timer_phi(void)
{
TCE0.CTRLA = TC_CLKSEL_DIV8_gc; // prescaling P
TCE0.CTRLB = TC_WGMODE_NORMAL_gc; // normal mode
TCE0.INTCTRLA = TC_OVFINTLVL_LO_gc;
TCE0.PER = 1440; // t = PER*FCPU/P =
// FCPU*P/32M = 1 us
}
ISR (TCE0_OVF_vect)
{
ptr = ptr +32;
if(ptr >= image + 32 * 360)
{
ptr = image;
} // send bytes to ledstrip
}
void init_inputcapture(void)
{
PORTC.PIN2CTRL = PORT_ISC_FALLING_gc;
PORTC.DIRCLR = PIN2_bm; // Pin 2 is input
EVSYS.CH0MUX = EVSYS_CHMUX_PORTC_PIN2_gc; // Select PC2 as input
// to event channel 0
TCC0.CTRLD = TC_EVACT_CAPT_gc | // Event capture
TC_EVSEL_CH0_gc; // for Channel 0
TCC0.CTRLB = TC0_CCAEN_bm; // Enable Inp. Capt. Ch. A
TCC0.CTRLA = TC_CLKSEL_DIV256_gc; // Start timer
TCC0.INTCTRLB = TC_CCAINTLVL_LO_gc; // Set Interr. level Ch. A
TCC0.PER = 0xFFFF;
}
ISR(TCC0_CCA_vect)
{
uint16_t v;
v = TCC0.CCA;
if (v > MIN_VALUE)
{ // skip if measured value is too small
line = 0; // reset image
TCE0.PER = (v * 360/(F_CPU / P)); // calculate periode
TCC0.CTRLFSET = TC_CMD_RESTART_gc; // restart input capture
}
}
void spi_write_byte(uint8_t data)
{
PORTC.OUTCLR = SPI_SS_bm;
spi_transfer(data);
PORTC.OUTSET = SPI_SS_bm;
}
uint8_t spi_read_byte(void)
{
uint8_t data;
PORTC.OUTCLR = SPI_SS_bm;
data = spi_transfer (FOO);
PORTC.OUTSET = SPI_SS_bm;
return data;
}
int main(void)
{
uint8_t i = 0;
spi_init();
PORTC.DIRSET = PIN0_bm;
PMIC.CTRL |= PMIC_LOLVLEN_bm;
sei();
PORTC.DIRSET = PIN4_bm | PIN5_bm | PIN6_bm | PIN7_bm;
while(1)
{
SPIC.DATA = i; // send i
while( ! (SPIC.STATUS & (SPI_IF_bm)) ); // wait until send
PORTC.OUTSET = PIN0_bm; // store
PORTC.OUTCLR = PIN0_bm;
_delay_ms(100);
i++;
}
}
Okay, so I got this code with no errors and warnings.
But when I run the program on my microcontroller ATXMega128A4U, I don't get the intended output.
There is a possibility that I didn't connect the pins of my 'ledstrip' in the right way with the pins of the microcontroller.
But if we consider that I did it like I intended to, the problem should be in the code.
The intended signal is 12 bytes long and with that I can turn RGB LED's on or off.
The RGB LED's are put together in a so called 'ledstrip'
Now what I'm getting is that some of the RGB LED's turn on and are Red Green or Blue.
What i should be getting is something like a chasing RGB LED row.
So you would see the LED's turn on or off at a certain frequency.

pic 18F4550: local variable problem,

I'm using the pic18F4550 with microchip v8.63 and with the C 18 compiler. I'm using a LDR that retrieve the value of the led (not on my picdem board) (red, green and blue) these values are stored in a variable after each conversion. Afther that when I press the button S2, I come into the method ISR: this part works.
But now: I try to compare the variable red, green and blue in the if's: but I think that it not happen, he just go to my 'else' (led RB3 on my picdem board burns).
#include <p18f4550.h>
/** V E C T O R R E M A P P I N G *******************************************/
extern void _startup (void); // See c018i.c in your C18 compiler dir
#pragma code _RESET_INTERRUPT_VECTOR = 0x001000
void _reset (void)
{
_asm goto _startup _endasm
}
#pragma code
void ISR (void);
#pragma code _HIGH_INTERRUPT_VECTOR = 0x001008
void _high_ISR (void)
{
_asm goto ISR _endasm
}
#pragma code _LOW_INTERRUPT_VECTOR = 0x001018
void _low_ISR (void)
{
;
}
#pragma code
/******************************************************************************/
// global variable, value off LDR.
unsigned int var1ADRESH = 0x00;
unsigned int color_red = 0;
unsigned int color_green = 0;
unsigned int color_blue = 0;
void main (void)
{
TRISD = 0x00; // PORTD als uitgang
RCONbits.IPEN = 0; // prioriteit uit
INTCONbits.GIE = 1; // enable interrupt
INTCONbits.RBIE = 1; // interrupt portB aan
//= set up port =
TRISAbits.TRISA0 = 1; // Set RA0/AN0 to input
//leds
TRISAbits.TRISA3 = 0;
TRISAbits.TRISA4 = 0;
TRISAbits.TRISA5 = 0;
LATAbits.LATA3 = 1;
LATAbits.LATA4 = 1;
LATAbits.LATA5 = 1;
ADCON0 = 0b00000000; // Set channel select to AN0
ADCON1 = 0b00001110; // Configure RA0/AN0 as analogue
ADCON2 = 0b10101010; // Right justified result
// TAD 12 and FOSC 32 - may need to adjust this
// depending on your clock frequency (see datasheet)
while(1)
{
_asm sleep _endasm
}
}
#pragma interrupt ISR
void ISR (void)
{
if (INTCONbits.RBIF==1) {
//conversie blauw
LATAbits.LATA3 = 0;
ADCON0bits.ADON = 1; // Enable ADC
// read LDR value.
ADCON0bits.GO = 1; // Set the GO bit of the ADCON0 register to start the conversion.
while (ADCON0bits.GO); // Wait until the conversion is complete.
ADCON2bits.ADFM = 0; // read result as 8-bit. (dus data in ADRESH) !
//= read data in ADRESH =
var1ADRESH = ADRESH; // reading value from LDR
color_blue = ADRESH; //waarde in blauw
//conversie rood
LATAbits.LATA3 = 1;
LATAbits.LATA4 = 0;
ADCON0bits.ADON = 1; // Enable ADC
// read LDR value.
ADCON0bits.GO = 1; // Set the GO bit of the ADCON0 register to start the conversion.
while (ADCON0bits.GO); // Wait until the conversion is complete.
ADCON2bits.ADFM = 0; // read result as 8-bit. (dus data in ADRESH) !
//= read data in ADRESH =
var1ADRESH = ADRESH; // reading value from LDR
color_red = ADRESH; //waarde in blauwe steken
//conversie groen
LATAbits.LATA4 = 1;
LATAbits.LATA5 = 0;
ADCON0bits.ADON = 1; // Enable ADC
// read LDR value.
ADCON0bits.GO = 1; // Set the GO bit of the ADCON0 register to start the conversion.
while (ADCON0bits.GO); // Wait until the conversion is complete.
ADCON2bits.ADFM = 0; // read result as 8-bit. (dus data in ADRESH) !
//= read data in ADRESH =
var1ADRESH = ADRESH; // reading value from LDR
color_green = ADRESH; //waarde in blauwe steken
// alles uitzetten
//PORTB = 0b1111111;
LATAbits.LATA5 = 1;
if(color_blue > color_red && color_blue > color_green){
//blauw
LATDbits.LATD0 = 1;
}
if(color_red > color_blue && color_red > color_green){
//rood
LATDbits.LATD1 = 1;
}
if(color_green > color_red && color_green > color_blue){
//groen
LATDbits.LATD2 = 1;
}
else {
LATDbits.LATD3 = 1;
}
}
INTCONbits.RBIF = 0;
}
Try to set all three of LATA3,4,5 before every readout?
Set TRIS for D0..2
I detect a few weird things (but I confess none might be the source).
Once you set the LATA bits, does the LDR immediately changes val? Of course not, but is it a matter of ns, us or ms?... I don't see any delays for LDR settling times.
You are always sleeping so it's probably required to set the ADON=1 (check DS). However, check the device DS for how long does the AD needs to get it's internals up and ready after setting ADON=1. On that subject, once ADON=1 you shouldn't and don't need to set it over again the the next two acquisitions.
The same thing about the format of the result. Set it once, and do it before the GO=1. Don't re-set every conversion.
If you're using only 8bit results, why the unsigned int? (btw, int is pretty dangerous in microcontrollers. Use short and chars and always explicit signdness).
Why the var1ADRESH assignment then color_xxx? when do the LATD bits eventually get =0?
Your If else only works on the last branch. I believe you intended a if{} else if{} else if... structure.

Resources