So what I am trying to do is receive a packet and print the payload to the serial port. Listening at the port is a python script that reassembles the payload and does some things with it.
Here is the code:
#include "mrfi.h"
int main(void)
{
BSP_Init();
MRFI_Init();
//Initialize the serial port
P3SEL |= 0x30;
UCA0CTL1 = UCSSEL_2;
UCA0BR0 = 0x41;
UCA0BR1 = 0x3;
UCA0MCTL = UCBRS_2;
UCA0CTL1 &= ~UCSWRST;
MRFI_WakeUp();
MRFI_RxOn();
__bis_SR_register(GIE+LPM4_bits);
}
//This is run when a packet is received
void MRFI_RxCompleteISR()
{
uint8_t i;
P1OUT ^= 0x02;
mrfiPacket_t packet;
MRFI_Receive(&packet);
char output[] = {" "};
for (i=9;i<29;i++) {
output[i-9]='a';
if (packet.frame[i]=='\r') {
output[i-9]='\n';
output[i-8]='\r';
}
}
TXString(output, (sizeof output));
}
I send a packet with test data but nothing. Anybody have any insights? Also while just so you know I am learning C while I do this, so any pointers on design would also be awesome.
Thanks.
I don't know why your code isn't working, but here are some design hints as requested.
Since this appears to be a hostless system, main() should most likely return void. I assume that you didn't post all of your code, as in a hostless there should also be an eternal loop in main().
Remove all "magic numbers" from the code and replace them with #defined bitmasks or constants.
Reduce all code inside interrupts to a minimum. The optimal interrupt only sets some flags.
Don't use unspecified width (output[]) for arrays/strings. Embedded system design is about making things deterministic and fixed.
Here is an example of another way to write that loop. As I have no idea what this program is supposed to do, replace the constant names with something that makes sense.
uint8_t output[OUTPUT_N];
memset(output, ' ', SPACES_N);
output[OUTPUT_N - 1] = '\0';
for(i=0; i < SOMETHING; i++)
{
output[i + A_OFFSET] = 'a';
if(packet.frame[i + FRAME_OFFSET] == '\r')
{
output[i + CR_OFFSET] = '\r';
output[i + LF_OFFSET] = '\n';
}
}
Related
So, I have a terminal connected to TxD0 and RxD0 pins. Let's say that I just want to test whether writing to it works after all.
I wrote few functions to make UART be able to read and write chars and strings. Although if I try to run it in the simulator, it gives me an overrun error.
Here are the functions in uart.c file:
void uart0_write(unsigned char reg_data)
{
while((U0LSR & (0x20)) != 0x20);/*wait until holding register is empty*/
U0THR = (int) reg_data;/*write to holding register*/
}
void uart0_write_str(char str[])
{
while(*str != '\0')/*check for EOF*/
{
uart0_write(*str);/*write a char*/
str++;
}
}
UART0 initialization function:
void uart0_init(void)
{
PINSEL0 = 0x05; /*set pin P0.0 to TXD0 and P0.1 RxD0 (TXD0 - 01; RxD0 - 01; 0101 = 0x05)*/
U0LCR = 0x83; /*set length for 8-bit word, set the stop bit, enable DLAB*/
U0IER = (1<<0) | (1<<1);/*enable RBR and THR interrupts*/
U0FCR = 0xC7; /*enable FIFO; reset Tx FIFO; set interrupt after 14 characters*/
/*Baud rate configured to 9600 Baud (from lecture notes)*/
U0DLL = 0x9D;
U0DLM = 0x0;
U0LCR = 0x03; /*8-bit character selection; disable DLAB*/
}
Exemplary use in main:
int main(void)
{
char *introMsg;
introMsg = "Hello World\n";
systemInit();
ADC_init();
timer0_init();
uart0_init();
uart0_write_str(introMsg);
/*or: */
while(1)
{
uart0_write('c');
}
return 0;
}
With these demonstrative code snippets the UART should work properly as I saw elsewhere on the web.
But when attempting to run it, it doesn't print anything and the OE pops up.
What am I doing wrong? I'm only starting to dive into the depths of bare metal programming, so there might be some bug that I didn't notice.
I'd welcome any insights!
Stay home,
Jacob
Currently, I have two, 2-Channel 1 Amp SPDT Signal Relay Controllers connected to my Raspberry Pi 3 via I2C, and when I currently run the function to turn one relay on, the other one will shut off at the same time (one or the other is on). In addition, my button to shut off relay 1 and my button to shut off relay 2 will shut both relays off.
My program is written in a windows form (visual studio), and I am accessing a C Shared Library via Dll Import, but I know for a fact my problem is within my C library. I am very new to C and how shifting works, so the root of my problem lies within the logic and structure of my code. Frankly, I'm confused on how to properly code this.
This is currently the method to turn Relay 1 On. It turns the relay on properly, but this also turns Relay 2 Off at the same time.
void Relay1On() ***CURRENTLY TURNS OTHER OFF WHEN ACTIVATED***
{
// Create I2C bus
int file;
char *bus = "/dev/i2c-1";
if ((file = open(bus, O_RDWR)) < 0)
{
printf("Failed to open the bus. \n");
exit(1);
}
// Get I2C device, MCP23008 I2C address is 0x20(32)
ioctl(file, I2C_SLAVE, 0x20);
// Configure all pins of port as output (0x00)
char config[2] = {0};
config[0] = 0x00;
config[1] = 0x00;
write(file, config, 2);
//Turn the first relay on
char data = 0x01;
config[0] = 0x09;
config[1] = data;
write(file, config, 2);
}
Here is the code for Relay 1 Off, I will not post Relay 2 On/Off because it is basically the same, Relay2On just has an added data += 1; after char data = 0x01;. Both 'Off' methods result in both relays shutting off.
void Relay1Off()
{
// Create I2C bus
int file;
char *bus = "/dev/i2c-1";
if ((file = open(bus, O_RDWR)) < 0)
{
printf("Failed to open the bus. \n");
exit(1);
}
// Get I2C device, MCP23008 I2C address is 0x20(32)
ioctl(file, I2C_SLAVE, 0x20);
// Configure all pins of port as output (0x00)
char config[2] = {0};
config[0] = 0x00;
config[1] = 0x00;
write(file, config, 2);
//Turn the first relay off *****Turns all off at the moment******
char data = 0xFE;
data = (data << 1);
config[0] = 0x09;
config[1] = data;
write(file, config, 2);
}
All I want is the methods to do as described, turn Relay 1 On when the method is called. When Relay1Off is called, shut only Relay 1 off. I'm sure it is simple, but as I've stated above C is quite new to me.
Thank you in advance for any contribution.
I don't know how the fancy ioctl stuff works, but I'd try to do all initialization outside of this function, including setting all the GPIO's to output.
You should probably just have one function call to set/clear a relay. I'd do something like this to start:
void RelayOnOff(unsigned char relay, unsigned char enable)
{
//Init to all off
static unsigned char data = 0x00;
...
if (enable){
data |= ( 1 << relay );
}
else{
data &= ~( 1 << relay );
}
config[0] = 0x09;
config[1] = data;
write(file, config, 2);
}
You pass in what relay you want to control, and a boolean value for enable/disable. If you make the data variable static, it'll "remember" that value from function call to function call. The enable/disable sets/clears the bit for whatever relay you pass in (0-7).
I'm programming a few libraries for a board with a PIC18F25K80 built-in. Right now I'm trying to program the UART library and I've tried everything but I cannot make it work when it comes to send a string of chars.
I'm using the XC8 compiler and I have the following code in the library: (I haven't programmed the interruptions yet, that's why you can't see anything related to that in the code.
void UARTsend(char data){
UARTbusy();
TXREG1 = data;
}
void UARTsendTEXT(unsigned char *text){
while(*text != '\0'){
UARTsend(*(text++));
}
}
char UARTbusy(){
return TXSTA1bits.TRMT;
}
And this code in the main file:
int main() {
UARTconfig(_BR_19200, _RxINT_OFF, _TxINT_OFF, _8BIT);
unsigned char data[20] = "ABCDEFGHIJ";
while(1){
if(UARTrxREAD() == 'a'){
UARTsendTEXT(data);
}
}
return 0;
}
So, when I hit 'a', the string should be sent but instead of seeing the string, I receive the first and last letter, and sometimes just the first letter.
Honestly, I believe it is a really basic problem with the code, but I tried everything I could think about and nothing worked, so maybe someone here can help me with that.
EDIT: just in case you need to check it out:
void UARTconfig(unsigned int BaudRate, unsigned int RxINT, unsigned int TxINT, unsigned int BIT){
int br_data;
//Clock configuration at 16MHz
OSCCONbits.IRCF = 0b111;
//9-bit transmit enable bit.
if(BIT == 1) {
RCSTA1bits.RX9 = 1; //Reception 9-bit.
TXSTA1bits.TX9 = 1; //Transmission 9-bit.
}
else {
RCSTA1bits.RX9 = 0; //Reception 8-bit.
TXSTA1bits.TX9 = 0; //Transmission 8-bit.
}
//Enable serial port.
RCSTA1bits.SPEN = 1;
//Enable continuous reception.
RCSTA1bits.CREN = 1;
//Setting asynchronous mode.
TXSTA1bits.SYNC = 0;
//Enable transmission
TXSTA1bits.TXEN = 1;
//Setting Rx/Tx pins as output.
TRISC7 = 0;
TRISC6 = 0;
//Baud rate configuration
BAUDCON1bits.BRG16 = 1; //16bit Baud Rate generator
TXSTA1bits.BRGH = 0; //Low speed BR.
switch(BaudRate){
case 0:
br_data=415;
break;
case 1:
br_data=103;
break;
case 2:
br_data=51;
break;
case 3:
br_data=16;
break;
case 4:
br_data=8;
}
SPBRGH1:SPBRG1 = br_data;
}
The function UARTbusy should be waiting for status, or its caller should be. But the transmit register status is read once and ignored.
There is typically a two-stage buffer for transmitted data. Values written to the interface register are held until the shift register is empty, and the device remains 'busy' until then.
When you write the first data, it is transferred immediately to the shift register, so writing the second data immediately is harmless. But you then keep on over-writing the contents of the output register until it holds the last character of your message. Then when the shift register becomes empty, the last character of your message is sent.
Remember that the shift register is shifting bits out relatively slowly - at the baud rate. That is why the status bit needs to be checked.
I am new to programming on micro controllers and I am trying to write a timer program for the PICLF1571. Every time it wakes from sleep, it's supposed to write to the flash memory. When I debug it with the simulation, it's able to write once, but once it loops the program gets stuck in the interrupt routine. If I comment out the Interrupt routine, the simulation jumps to another place or goes to 0x00.
The only time I see the program get stuck is when the function flash_write is used.
What could be some causes for interrupts to occur if no flags are triggered?
pin setup
void init(void){
ANSELA = 0x0; //|-> Pin setup
TRISA = 0x0;
TRISAbits.TRISA5 = 1;
PORTA = 0x0;
LATA = 0x0;
INTCONbits.GIE = 1; //|-> Interrupt setup
INTCONbits.IOCIE = 1;
IOCAP = 0x0;
IOCAPbits.IOCAP5 = 0;
INTCONbits.IOCIF = 0;
IOCAF = 0x0;
IOCAFbits.IOCAF5 = 0;
WDTCONbits.SWDTEN = 1; //|-> Watchdog Timer setup
WDTCONbits.WDTPS = 0b00001;// reconfigure for correct speed
//currently 0b10001
}
main
//#include <stdio.h>
#include <xc.h>
#include "init.h"
#include "Interrupt.h"
#include "flash.h"
int main(void){
init();
unsigned short ad = 1;
unsigned short f = 0x3FFF;
unsigned short a = 0x0000;
unsigned short ret = 0x0000;
flash_erase(0x0000);
while(1) {
asm("sleep");
flash_write(a,f);
//flash_erase(a);
//flash_read1(a,&ret);
}
return 1;
}
flash_write function. Instructions based on flowchart in datasheet
void flash_write(unsigned short addr, unsigned short data){
INTCONbits.GIE = 0; //||]->start write
PMCON1bits.CFGS = 0;//||]
PMADRH = (unsigned char)((addr >> 8) & 0xFF);
PMADRL = (unsigned char)(addr & 0xFF);
PMCON1bits.FREE = 0;//||]->enable write
PMCON1bits.LWLO = 1;//||]
PMCON1bits.WREN = 1;//||]
PMDATH = (unsigned char)((data >> 8) & 0xFF);
PMDATL = (unsigned char)(data & 0xFF);
PMCON1bits.LWLO = 0;
PMCON2 = 0x55; //||]->unlock sequence
PMCON2 = 0xAA; //||]
PMCON1bits.WR = 1; //||]
NOP(); //||]
NOP(); //||]
PMCON1bits.WREN = 0;//]->end write
INTCONbits.GIE = 1;
asm("RETURN");
}
interrupt routine
#include <xc.h>
void interrupt button(void){
if (INTCONbits.IOCIE == 1 && IOCAFbits.IOCAF5 == 1 ){
int time = 0;
while (PORTAbits.RA5 == 1){//RA5 in sim never changes. always 0
time++;
if (time >= 20000 && PORTAbits.RA5 == 1){
LATA = 0x0;
asm("NOP");
break;
}
if ( time < 20000 && PORTAbits.RA5 == 0){
asm("NOP");
break;
}
}
IOCAF = 0x0;
INTCONbits.IOCIF = 0;
asm("RETFIE");
}
}
0000h is the reset vector address; once written, subsequent resets will jump to 0x3fff, which is not a valid address on a device with only 0x3ff words of flash. Note that since 0x3fff is the erased state of flash memory, the write in this case actually has no effect that is not already caused by the erase alone.
Also understand that, the PIC12 flash memory is word-write/row-erase, and a row is 16 words. So the erase operation will wipe out the entire vector table and the start of the program area too. You are essentially modifying the code, but not in a manner than makes any sense (if it makes sense at all).
You should reserve an area of flash using appropriate linker directives and well away from the vector table (probably the entire last row at 0x3f0, to prevent the linker locating code in the space you want to write at run time.
Another issue is that the flash cell endurance on PIC12F1571 is only 10000 erase/write cycles - are you sure you want to write to the same address every time the device boots? If you "stripe" the reserved row and write to each of the 16 words in turn before erasing the row and restarting, you will increase endurance to 160000 cycles. Add more rows to get greater endurance. Since erased flash has a value 0x3fff (14 bit words), to find the "current value" you need to scan the reserved row(s) for the last value that is not 0x3fff (0x3fff is implicitly therefore not a valid actual value).
Here I need to output a waveform on oscilloscope in C which should in a rising sawtooth waveform.I am not sure if my code is correct. Any help or suggestions?
while(1)
{
for (i = 1; i < 360; i++);
// Check to see if status.TRDY is 1
while(*(base+2) & 0x40 != 1);
// while shift register is not empty
// Make the sawtooth pattern
if (saw == 0x1fff){
saw = 0x1000;
}
else {
saw = saw+1;
}
// transmit sawtooth to the oscilloscope
*(base+1) = saw;
}
This only tidies up the OP's posted code. It does not answer how to program the DAC. OP is using a 16-bit amplitude value but his register addressing suggests 8-bit registers - perhaps two writes are needed.
I suggest you also need function arguments defining the period of the sawtooth wave, and the number of steps. You also need an exit condition. I leave these points to you.
#Chris Stratton also commented that the I/O port should be the correct language type.
#define MINSAW 0x1000
#define MAXSAW 0x1FFF
unsigned *base = (unsigned *)0xD000; // "insert your value"
int main() {
unsigned saw, i;
while(1) {
for (i = 0; i < 360; i++) {
// ratio the waveform amplitude
saw = MINSAW + i * (MAXSAW - MINSAW) / 359;
// Check to see if status.TRDY is 1
while((*(base+2) & 0x40) != 0x40);
// transmit sawtooth to the oscilloscope
*(base+1) = saw;
}
}
return 1;
}