I am currently working on a project to select different outputs based on a text input from a laptop via USB.
What I am currently trying to do is send a character out from my PIC18F1320 to HyperTerminal, I have tried using variables but was recieveing rnadom characters such as smiley faces etc.
I simplified my code to simply print a 1 however I am still recieving smily face symbols. I have checked that I am using the correct baud rate and there is definite communication between my laptop and the PIC, however at this point I am completely stuck as I have no idea why random characters are being output.
I have extremely little knowledge of C and any help would be appreciated
#include <p18f1320.h>
#include <usart.h>
#include <stdio.h>
#include <stdlib.h>
void main()
{
OSCCON = 0x70; // 8MHz internal clock
// Configure USART
OpenUSART( USART_TX_INT_OFF &
USART_RX_INT_OFF &
USART_ASYNCH_MODE &
USART_EIGHT_BIT &
USART_CONT_RX &
USART_BRGH_LOW,
12);
while (1)
{
putrsUSART("1");
}
CloseUSART();
}
The internal RC oscillator on the PIC is not precise enough to run the USART at the desired speed - it can vary by ±2% from the expected frequency, which is probably far out enough to be causing the errors you're seeing. You will need to attach and configure an external crystal for correct results.
Put your data in RAM and send. See Harvard Architecture
char buf[10];
strcpy(buf, "Hello\n"); // This should cal special ROM to RAM strcpy();
putrsUSART(buf);
Note: "I have checked that I am using the correct baud rate" may not be right. Until you received valid data, I would not be too confident about this.
Related
good day, stm32 nucleo board I want to write informative Log messages using.
For example, I want to display the message that the program has started by using the Log("Program started") function when the program starts during this period, or I want to give the error message to the screen by using the Log("Program Failed') function when the program fails.
I using C programming langue and stm32cubeide & Nucleo f207zg board thanks in advance for your help
Thanks I solved the problem
Given that:
You know what the UART/USART peripheral is
You connected the right pins to a serial interface
You connected the other end of the interface (for instance an FTDI chip) to your computer
You can implement the logging with printf as you would do in C. Why? Because printf already takes care for you the formatting of the strings, which no one wants to reimplement, and then you redirect the printf output to the UART peripheral that handles low level serial protocol.
Following this guide the steps are easy enough:
Add #include <stdio.h> to the Includes section at the top of the main.c
#include "stdio.h"
Copy and paste the following code into the main.c file before the main() function but after the UART handle declaration
Note that you need to replace the question mark with the actual UART handle declaration, for instance huart1
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart?, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
return ch;
}
As pointed out by Fra93, you need to implement UART/USART protocol communication and print stuff to there. I'm writing this reply, because I'm getting a feeling you have some basic experience writing desktop applications, but not embedded, so I will clarify a few points.
There is no console to print to. There are no logs. They simply don't exist. At all. Not in a desktop app development sense.
What's usually done is that one of the UARTs of the MCU is used to print characters to the ST-Link, which converts it to USB (alternatively, can be FTDI IC, CP2102 or other USB-UART bridges/converters). So then your MCU will send out characters over UART, and the USB-UART converter will display them in a COM port terminal (programs like PuTTy)
If you start with empty project and no external libraries used, you will need 3 dozen lines of code alone just to be able to print stuff. Initially, you have nothing. You have to initialize UART, configure it, then implement how it handles characters, numbers. You need to literally write a basic UART driver. And you can call printing function whatever you want. You can call it Log("hello world"), you can call it Whisper("hi there"). Because you will actually create this function. You're the boss.
Now, given you are not very familiar with all of this, it may sound like a difficult task. And it most certainly is. Writing a driver from scratch on your day 1 is not a thing you want to do (unless you're into that kind of stuff on day 1).
I would strongly advise you to get some library, such as HAL by STMicroelectronics, and familiarize yourself with what it can do - including how to print stuff with UART. Internet is flooded with articles and videos of how to use UART with HAL, it's literally one of the first things to be implemented. Specifically for the reason, that it works like logs and simplifies further development/learning.
So, in order to get "logs" working, I would do the following:
Get HAL for your specific MCU
Familiarize yourself with UART - basic stuff about what it is and how it works. No need to be an expert, just learn what it is.
Familiarize yourself with how to use UART with HAL
From the schematic of the PCB of your nucleo board, find out which UART of the MCU is connected to ST-Link (I checked the schematic: it's USART3)
Get serial port (COM) terminal program for your computer
Use HAL to initialize USART3 and print to USART3. Whatever you print there will be visible in the terminal. Yes, you will not see anything in the IDE. You need a separate program to display what you receive via USB COM port.
In the end, your print function will be the one proposed by Fra93. HAL_UART_Transmit is the most basic HAL function to send stuff via UART. If you're very picky about using "Log" as a function you call to print via UART, you can always wrap HAL_UART_Transmit into your own function called Log.
I have a BeagleBone Black board and I'm using the below-mentioned image file.
https://debian.beagleboard.org/images/bone-debian-10.3-iot-armhf-2020-04-06-4gb.img.xz
I aim to operate GPIO pins of this board with the c programming language.
To do so, I've gone through this link: https://beagleboard.org/static/librobotcontrol/installation.html
And after following all the steps according to this link the result I achieved is the same as mentioned in the checking functionality step [the last step] of this document.
Furthermore, I follow this document for c language setup:
https://github.com/beagleboard/librobotcontrol/blob/master/docs/src/project_template.dox
and run this source code:
https://beagleboard.org/static/librobotcontrol/rc_test_leds_8c-example.html
All these processes were completed without any error.
##################################
Now I want to access the GPIO pins of the board. For that, I've prepared a basic code.
Let's take a pin P8_10 / GPIO2[4] for an example. So for that my code will be:
#include <stdio.h>
#include <rc/led.h>
#include <rc/gpio.h>
#include <rc/time.h>
//#define WAIT_US 500000 // time to light each LED in microseconds
int main()
{
rc_gpio_init(2,4,GPIOHANDLE_REQUEST_OUTPUT); /* declare as output*/
rc_gpio_set_value(2,4,1); /* set high */
rc_gpio_cleanup(2,4);
return 0;
}
After executing this code I am not getting the expected output.
So have you any suggestions for me regarding this code.
Or is there any other way to do so?
Thank you.
Try config-pin gpio
config-pin p9.9 gpio
Then try your source. If that does not work and if getting the gpio pins muxed on the BBB is giving you issues. You can always test your specific pin w/:
config-pin -q <Your Specific Pin Used>
For instance: config-pin -q p9.9 will tell you how it is muxed.
Also, most pins can be found by a testing script by mvduin.
Here is the site online at github: https://github.com/mvduin/bbb-pin-utils
Here: https://beagleboard.org/Support/bone101
That site, once scrolling downward, shows a bunch of different ways to mux your BBB w/ GPIO, i2c, UART, and so on...
This and more can be a good base for working w/ the BBB outside of programming w/ the C language under the librobotcontrol library.
Also, here is a good starter on the way GPIO is handled in the C lib. in question: https://beagleboard.org/librobotcontrol/group___g_p_i_o.html
I have a Cincoze DE-1000 industrial PC, that features a Fintek F81866A chipset. I have to manage the DIO pins to read the input from a phisical button and to set on/off a LED. I have experience in C++ programming, but not at low/hardware level.
On the documentation accompanying the PC, there is the following C code:
#define AddrPort 0x4E
#define DataPort 0x4F
//<Enter the Extended Function Mode>
WriteByte(AddrPort, 0x87)
WriteByte(AddrPort, 0x87) //Must write twice to entering Extended mode
//<Select Logic Device>
WriteByte(AddrPort, 0x07)
WriteByte(DataPort, 0x06)
//Select logic device 06h
//<Input Mode Selection> //Set GP74 to GP77 input mode
WriteByte(AddrPort, 0x80) //Select configuration register 80h
WriteByte(DataPort, 0x0X)
//Set (bit 4~7) = 0 to select GP 74~77 as Input mode.
//<input Value>
WriteByte(AddrPort, 0x82) // Select configuration register 82h
ReadByte(DataPort, Value) // Read bit 4~7(0xFx)= GP74 ~77 as High.
//<Leave the Extended Function Mode>
WriteByte(AddrPort, 0xAA)
As far as I understood, the above code should read the value of the four input PINs (so it should read 1 for each PIN), but I am really struggling to understand how it actually works. I have understood the logic (selecting an address and reading/writing an hex value to it), but I cannot figure out what kind of C instructions WriteByte() and ReadByte() are. Also, I do not understand where Value in the line ReadByte(DataPort, Value) comes from. It should read the 4 PINs all together, so it should be some kind of "byte" type and it should contain 1 in its bits 4-7, but again I cannot really grasp the meaning of that line.
I have found an answer for a similar chip, but it did not help me in understanding.
Please advice me or point me to some relevant documentation.
That chip looks like a fairly typical Super I/O controller, which is basically the hub where all of the "slow" peripherals are combined into a single chipset.
Coreboot has a wiki page that talks about how to access the super I/O.
On the PC architecture, Port I/O is accomplished using special CPU instructions, namely in and out. These are privileged instructions, which can only be used from a kernel-mode driver (Ring 0), or a userspace process which has been given I/O privileges.
Luckily, this is easy in Linux. Check out the man page for outb and friends.
You use ioperm(2) or alternatively iopl(2) to tell the kernel to allow the user space application to access the I/O ports in question. Failure to do this will cause the application to receive a segmentation fault.
So we could adapt your function into a Linux environment like this:
/* Untested: Use at your own risk! */
#include <sys/io.h>
#include <stdio.h>
#define ReadByte(port) inb(port)
#define WriteByte(port, val) outb(val, port)
int main(void)
{
if (iopl(3) < 0) {
fprintf(stderr, "Failed to get I/O privileges (are you root?)\n");
return 2;
}
/* Your code using ReadByte / WriteByte here */
}
Warning
You should be very careful when using this method to talk directly to the Super IO, because your operating system almost certainly has device drivers that are also talking to the chip.
The right way to accomplish this is to write a device driver that properly coordinates with other kernel code to avoid concurrent access to the device.
The Linux kernel provides GPIO access to at least some Super I/O devices; it should be straightforward to port one of these to your platform. See this pull request for the IT87xx chipset.
WriteByte() and ReadByte() are not part of the C language. By the looks of things, they are functions intended to be placeholders for some form of system call for the OS kernel port IO (not macros doing memory mapped IO directly as per a previous version of this answer).
The prototypes for the functions would be something along the lines of:
#include <stdint.h>
void WriteByte(unsigned port, uint8_t value);
void ReadByte(unsigned port, uint8_t *value);
Thus the Value variable would be a pointer to an 8 bit unsigned integer (unsigned char could also be used), something like:
uint8_t realValue;
uint8_t *Value = &realValue;
Of course it would make much more sense to have Value just be a uint8_t and have ReadByte(DataPort, &Value). But then the example code also doesn't have any semicolons, so was probably never anything that actually ran. Either way, this is how Value would contain the data you are looking for.
I also found some more documentation of the registers here - https://www.electronicsdatasheets.com/download/534cf560e34e2406135f469d.pdf?format=pdf
Hope this helps.
I am using the 8051 microcontroller to read, write, and erase from flash memory.
Attached are the waveform for programming operations
And below is the code that I have written in order to recreate the waveform in order to write data into the chip:
void quick_write_op(void)
{
unsigned char i;
char SFRPAGE_SAVE=SFRPAGE;
SFRPAGE=CONFIG_PAGE;
//test=1;
Vpp_en=0; //8 volts is supplied to the board. Read/Write operations allowed
//Wait at least 1us between Vpp high and CSn low
for(i=0;i<2;i++){}
//Set-Up program command
P5=0x40;CSn=0;WEn=0;WEn=1;CSn=1;
//Program Command (Latch Address & Data)
P5=data_byte;CSn=0;WEn=0;WEn=1;CSn=1;
//Wait at least 10us for programming
for(i=0;i<23;i++){}
//Program Verify Command
P5=0xC0;CSn=0;WEn=0;WEn=1;CSn=1;
//Wait at least 6us for program verify
for(i=0;i<17;i++){}
//Program Verification
P5MDOUT=0x00; //Configured pins to open-drain
CSn=0;OEn=0;
OEn=1;CSn=1;
//Resets the command register
P5MDOUT=0xFF;
P5=0x00;CSn=0;WEn=0;WEn=1;CSn=1;
Vpp_en=1; //8 volts is now removed
//test=0;
SFRPAGE=SFRPAGE_SAVE;
}
I am going to assume that this code is fairly simple to follow seeing that there is a picture to go along with it detailing what I should do. If for some reason that it is hard to follow, then please let me know and I will clarify by adding code, images, etc.
I don't believe that there is a timing issue anywhere as I have checked that with a logic analyzer. When I invoke the write command, I want to write a 0x55 to address 0x00000, I should expect to see a 0x55 at address 0x00000. Instead, I am reading back an empty address, 0xFF. Therefore being forever stuck in the WRITE_LOOP until the right data is read in. Of course I may be blinded by my own bias so if I could get extra pairs of eyes on this and advice then I would greatly appreciate it. Thank you all.
I have microprocessor at32uc3b0256 and I want turn on leds, (simple program from examples). To do this I use Atmel Studio. I found sample code:
#ifndef F_CPU
#define F_CPU 16000000UL // 16 MHz clock speed
#endif
#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
DDRC = 0xFF; //Makes PORTC as Output
while(1) //infinite loop
{
PORTC = 0xFF; //Turns ON All LEDs
_delay_ms(1000); //1 second delay
PORTC= 0x00; //Turns OFF All LEDs
_delay_ms(1000); //1 second delay
}
}
But when i wrote it to Atmel Studio i got some errors, Atmel Studio dont see DDRC and PORTs as variable. How can I fix it?
Screen form Atmel Studio
You are using GPIO example for AVR8 architecture. AVR32 architecture is completely different introducing GPIO module as separate HW block connected through PBA (I think). There are no registers like DDRC,...
You can look at AVR32 architecture as on network of subcomponents where MCU core is only one of the modules. There are 2 main buses PBA and PBB each connected to different modules.
To make AVR32 firmware work you need do this:
configure and start main MCU core clock you want to use
AVR32 MCU core is usually running at low 32KHz clock after reset. To achieve better performance you need higher clock up to 66MHz. I usually start PLL at some common frequency and divide all clocks (CPU,PBA,PBB,HSB) from it later. As a source for the PLL you need some clock for example internal RC or oscillator driven by external crystal. If you want also USB then you need to take in mind it needs specific frequency so compromise ... For more info check SCIF module in datasheet and or in examples.
switch to it when started properly
Either wait a bit (100ms) or check if clock is running directly (SCIF module has some capabilities for it I think).
configure/start used HW modules
now do your stuff
Bootlaoder
Another thing you need to take care of is the boot loader. I do not like JTAG as I have a bad experience with it (does not take much to fry it and the programing with it is really uncomfortable). With JTAG you can easily wipe out bootloader (each chip is shipped with it) and trust me getting it back to work is really nasty.
Bootloader on the other hand is simple and elegant. For example I use FLIP and has simple comandline file for programing chip. Then I just open command prompt execute it. And on each rebuild/programming I just hit up arrow to repeat last command in the prompt and hit enter. In comparison to many clicks with JTAG is this much faster and simpler. Here example of the cmd:
avr32-objcopy -O ihex AT32UC3L064.elf AT32UC3L064.hex
Batchisp -device AT32UC3L064 -hardware RS232 -port COM1 -baudrate 115200 -operation onfail abort memory flash erase f blankcheck loadbuffer AT32UC3L064.hex program start reset 0
The avr32-objcopy.exe is in the AVR studio bin directory.
With Bootloader you need to tell the compiler your program is not starting at 0x0000 because that would be overlapping with bootloader. To do that see the trampoline examples.
This is how my AVR32 app usually looks like:
#include <avr32/io.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "intc.c"
#include "gpio.c"
#include "pm_uc3l.c"
#include "scif_uc3l.c"
#include "adcifb.c"
#include "flashcdw.c"
#include "pdca.c"
//#include "pwma.c"
#include "tc.c"
#include "usart.c"
#include "eic.c"
#include "genclk.h"
#include "osc.c"
#include "dfll.c"
#include "sysclk.c"
#include "status_codes.h"
#include "cycle_counter.h"
#include "sleep.h"
#include "delay.c"
#define cpu_clk 30000000
#define _LED AVR32_PIN_PA04
void system_init()
{
delay_init(115000);
Disable_global_interrupt();
INTC_init_interrupts();
scif_start_rc120M();
delay_ms(100);
pm_set_clk_domain_div((pm_clk_domain_t)AVR32_PM_CLK_GRP_CPU,PM_CKSEL_DIVRATIO_4);
pm_set_clk_domain_div((pm_clk_domain_t)AVR32_PM_CLK_GRP_PBA,PM_CKSEL_DIVRATIO_4);
pm_set_clk_domain_div((pm_clk_domain_t)AVR32_PM_CLK_GRP_PBB,PM_CKSEL_DIVRATIO_4);
pm_set_clk_domain_div((pm_clk_domain_t)AVR32_PM_CLK_GRP_HSB,PM_CKSEL_DIVRATIO_4);
pm_set_all_cksel(SCIF_RC120M_FREQ_HZ,cpu_clk,cpu_clk,cpu_clk);
flashcdw_set_flash_waitstate_and_readmode(cpu_clk);
pm_set_mclk_source(PM_CLK_SRC_RC120M);
delay_init(cpu_clk);
}
//------------------------------------------------------------------------------------------------
void wait_ms(U32 dt)
{
U32 t0,t1;
t0=Get_system_register(AVR32_COUNT);
dt=((dt*cpu_clk)+999)/1000;
t0&=RDTSC_mask;
for (;;)
{
t1=Get_system_register(AVR32_COUNT);
t1&=RDTSC_mask;
if (t0>t1) t1+=RDTSC_mask+1;
if ((t1-t0)>=dt) break;
}
}
//------------------------------------------------------------------------------------------------
void wait_us(U32 dt)
{
U32 t0,t1;
t0=Get_system_register(AVR32_COUNT);
dt=((dt*cpu_clk)+999999)/1000000;
t0&=RDTSC_mask;
for (;;)
{
t1=Get_system_register(AVR32_COUNT);
t1&=RDTSC_mask;
if (t0>t1) t1+=RDTSC_mask+1;
if ((t1-t0)>=dt) break;
}
}
//------------------------------------------------------------------------------------------------
int main(void)
{
system_init();
// here init what you need
gpio_configure_pin(_LED,GPIO_DIR_OUTPUT|GPIO_INIT_HIGH);
for (;;)
{
// here do your stuff
gpio_tgl_gpio_pin(_LED);
wait_ms(200);
}
//------------------------------------------------------------------------------------------------
I do not use framework manager instead I include the stuff myself... and my framework is rewritten to avoid unnecessary includes and slowdowns of compilation. Also beware that framework updates are not always compatible so sometimes after update your code will not compile ... It is better to have one solid framework and not update it unless you really need to.
Select only the modules you need to (no need to include them all). For example you need intc,gpio,scif etc my includes are from bigger project so many of them are useless for you and also not all headers/modules are available for all of the AVR32 chips.
I got a bit off topic (I think was necessary) so back to GPIO
The API and architecture is completely changed. Do not be fooled by the pin names. For example pin PA35 does not mean port A pin 35 !!! There is no port PA It is just naming convention without any real meaning to the architecture which is a bit silly and took me a while to got along with it. There are as many ports as needed to cover all the pins. Each port support 32 pins and the pin number is the real thing you need to know.
Each pin is defined somewhere in avr32/io.h as a define like AVR32_PIN_PA04 and it contains numerical value of the pin position in chips GPIO. To obtain gpio port/mask you just do this:
port = pin>>5
mask = 1<<(pin&31)
Now to access GPIO registers directly I recommend to look at gpio.c. You can set,res,test,read 32 pins at a time to speed up (if they are at the same port). The speed is dependent mainly on the buss clock (usually PBA for GPIO) so if your clock for it is low do not expect high toggle rate. beware GPIO access is slow and if not used wisely can kill the performance of your code...
If HW pins selected for your App are done wisely you can have really fast speeds. For example I got toggle speeds around 2-5 MHz !!!
Here example of setting a pin from gpio.c
void gpio_set_gpio_pin(uint32_t pin)
{
U32 bit= 1 << (pin & 0x1F);
volatile avr32_gpio_port_t *gpio_port = &GPIO.port[pin >> 5];
gpio_port->ovrs = bit; // Value to be driven on the I/O line: 1.
gpio_port->oders = bit; // The GPIO output driver is enabled for that pin.
gpio_port->gpers = bit; // The GPIO module controls that pin.
}
You can use this to set multiple pins at the same port simply by exchanging bit with the mask of all pins you want to set ...
If you are using Interrupts for GPIO beware that the interrupt controller INTC is also a separate module connected by buss and wrongly set clock or wait states can cause huge problems.