PIC16F877 display the result of ADC on LEDs with C language using MPLAB - embedded

I used PIC16F877 and my purpose is to choose CHANNEL 4 to display the analogue input AN4 value on PortD leds. The approximate value is about 1V. I wrote a code and however, no matter how I ran my code, there're not reaction with the GPIO monitor.
By the way, do I write ReadADC1() in the while(1){} loop? I tried that, but there's no help. Thanks.
#include <xc.h>
#define LEDs PORTD
#include "prologue.c"
unsigned char ReadADC1(void) {
ADCON0 |= 0b00000010;
while ( (ADCON0 & 0b00000010) );
return ADRESH;
}
main ()
{
// declare variables if any required
TRISA= 0B00100000;
ANSEL=0B00010000;
ADCON0 = 0b11010001;
ADCON1 = 0b10000000;
LEDs=ReadADC1();
//*** your code for initialisation if required
//*** end of your initialisation
//*** your code for the superloop
while (1) {
}
//*** end of the superloop
}
There's no reaction with the GPIO pins monitor. I restarted the IDE many times.

By default all ports are configured as an input. If you want want use a port as an output you had to change the configuration:
TRISD = 0x00;
Another issue:
There is no ANSEL register in this controller, you had to do the selection (digital or analog input) with ADCON1register.

Related

TM4321GH6PM - why is GPIODATA register initializing itself and how to read and write to it properly?

Context: I am following a Embedded Systems course that uses the TM4C321GHP6M microcontroller. The IDE being used is the uvision ide by keil. The purpose of the program I am running is to turn on an on-board LED using PF2 and when Switch 1, connected via PF4, is pressed the led will blink. Once switch 1 is released it LED will go back to just being ON.
// BranchingFunctionsDelays.c Lab 6
// Runs on LM4F120/TM4C123
// Use simple programming structures in C to
// toggle an LED while a button is pressed and
// turn the LED on when the button is released.
// This lab will use the hardware already built into the LaunchPad.
// Daniel Valvano, Jonathan Valvano
// January 15, 2016
// built-in connection: PF0 connected to negative logic momentary switch, SW2
// built-in connection: PF1 connected to red LED
// built-in connection: PF2 connected to blue LED
// built-in connection: PF3 connected to green LED
// built-in connection: PF4 connected to negative logic momentary switch, SW1
#include "TExaS.h"
#define GPIO_PORTF_DATA_R (*((volatile unsigned long *)0x400253FC))
#define GPIO_PORTF_DIR_R (*((volatile unsigned long *)0x40025400))
#define GPIO_PORTF_AFSEL_R (*((volatile unsigned long *)0x40025420))
#define GPIO_PORTF_PUR_R (*((volatile unsigned long *)0x40025510))
#define GPIO_PORTF_DEN_R (*((volatile unsigned long *)0x4002551C))
#define GPIO_PORTF_AMSEL_R (*((volatile unsigned long *)0x40025528))
#define GPIO_PORTF_PCTL_R (*((volatile unsigned long *)0x4002552C))
#define SYSCTL_RCGC2_R (*((volatile unsigned long *)0x400FE108))
#define SYSCTL_RCGC2_GPIOF 0x00000020 // port F Clock Gating Control
// basic functions defined at end of startup.s
void DisableInterrupts(void); // Disable interrupts
void EnableInterrupts(void); // Enable interrupts
void Delay100ms(unsigned long time);
void init(void);
int main(void){
TExaS_Init(SW_PIN_PF4, LED_PIN_PF2); // activate grader and set system clock to 80 MHz
init();// initialization goes here
EnableInterrupts(); // enable interrupts for the grader
while(1){
unsigned long in;
Delay100ms(1);
in = GPIO_PORTF_DATA_R & 0x10; //read switch
if(in == 0x00){//if PF4 == 0 (switch is pressed)
GPIO_PORTF_DATA_R ^= 0x04; //toggle PF2
}
else{//if PF4 == 1 (switch not pressed)
GPIO_PORTF_DATA_R = 0x04; //set PF2 so LED is ON
}
}
}
void init(void){
SYSCTL_RCGC2_R = SYSCTL_RCGC2_GPIOF; //turn on clock for Port F
Delay100ms(1);
GPIO_PORTF_AMSEL_R = 0x00; //clear PF4 and PF2 bits in port F AMSEL to disable analog
GPIO_PORTF_PCTL_R = 0x00; //clear PF4 and PF2 bit fields in Portf PCTL to config as GPIO
GPIO_PORTF_DIR_R = 0x04; //Set port F dir reg so PF4 is in and PF2 is out
GPIO_PORTF_AFSEL_R = 0x00; //clear PF4 and PF2 bits in port F AFSEL to disable alt func
GPIO_PORTF_DEN_R = 0x14; //set PF4 and PF2 bits in Port F DEN to enable digital
GPIO_PORTF_PUR_R = 0x10; //set PF4 bit in Port F PUR to activate internal pullup
GPIO_PORTF_DATA_R = 0x04; //set PF2 bit in Port F DATA so the LED is init on
PF2 = 0x20;
}
void Delay100ms(unsigned long time){
unsigned long i = 1333333;
while(time > 0){
while(i > 0){
i--;
}
time--;
}
}
For some reason once the program goes to the init() function and steps over SYSCTL_RCGC2_R = SYSCTL_RCGC2_GPIOF; and then Delay100ms(1); the register GPIO_PORTF_DATA_R is initialized with value 0x011. I am not sure what is causing this. Additionally when I attempt to set GPIO_PORTF_DATA_R = 0x04 it then holds the value 0x15? This behavior is very strange and after reading through the data sheet I can see that GPIODATA is read and written to in a unconventional way. For reference please see pages 662 and 654. Would anyone be able to explain this behavior and how I could properly read and write to this register?
This line:
SYSCTL_RCGC2_R = SYSCTL_RCGC2_GPIOF; //turn on clock for Port F
enables the GPIOF clock. When the clock for a peripheral is not running its registers cannot be read or written. So in the debugger you do not see the register value until after the clock is enabled.
Although the reset state of GPIODATA is documented as 0x00000000, that is only true for output the default state of GPIODIR sets every GPIO pin to an input. So 0x11 simply reflects the input state of that port, and PF0 and PF4 happen to be in the logic-high state.
You would need to consult the board schematic to determine what is connected to those pins and why they might be in the high state, but you have already mentioned that PF4 is connected to SW1, and the code sets that pin as an input with internal pull-up. I am guessing that this is a Tiva LaunchPad board having:
Pressing the SW1 push-button will pull the pin low, and the PF4 pit will become zero. The internal pull-up resistor is enabled by default for PF4, so it is not floating even though you have not yet configured it at that point. PF0 GPIOPUR default is floating (per table 10-8), so unless it is configured explicitly to pull-up, its state is indeterminate when connected as on the LaunchPad to SW2.
With respect to perceived "unconventional" behaviour, all peripheral registers on any MCU behave as defined by their manufacturer documentation according to the hardware design. Hardware registers are not RAM (even when memory-mapped) and need not behave like RAM. In particular, unlike RAM, they may have deterministic reset state, and be either read-write, read-only, or write-only. Writing a bit need not modify that bit, registers may change value independently of reads or writes by code.

Static declaration of '__vector_1' follows non-static declaration

Im trying to create a program which will interrupt when I press the button. I have Atmega8 and I use Microchip studio for coding.
I checked the document about interrupts on atmega's website however I can't say I totally got it.
Here is my code:
#define F_CPU 1000000UL
#define IRQ1 INT0_vect
#define IRQ2 INT1_vect
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
void init()
{
DDRB=0b11111111;
PORTB=255;
_delay_ms(2000);
PORTB=0;
DDRD = 0b00000000;
GICR=0xc0;
MCUCR=0x08;
}
int main(void){
init();
volatile int mode = 0;
ISR(IRQ1){
_delay_ms(500);
if (mode<3)mode++; else mode = 0;
}
ISR(IRQ2){
_delay_ms(150);
}
}
Errors I get:
Imgur
I would be glad if any admin edits my question and add picture here, website doesn't let me add photo because I need at least 10 reputation to post image
Don't try to define functions inside of other functions unless you really know what you are doing. You should move the ISR definitions to the top level of the file, putting them outside of main.

STML4 USB virtual com port

I have the nucleo board (nucleo-L4R5ZI) and want to write a code to be able to send data from a uC to a PC via the USB. I followed some tutorials, used STM32CubeMx, other solutions found across the Internet, but anyways I failed. I can open the vcp on the PC side (using Hterm, TeraTerm and Realterm), but cannot get any data.
I use Eclipse and the buildin debugger, which I flashed to JLink.
The main loop:
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USB_DEVICE_Init();
HAL_Delay(10000);
uint8_t HiMsg[] = "0123456789987654321001234567899876543210\r\n";
while (1)
{
if( CDC_Transmit_FS(HiMsg, 20) == USBD_OK )
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_7); // blue LED
}
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_14); // red LED
HAL_Delay(1000);
}
}
After executing this function, the blue LED lights only once and never changes its state (does not blink). It means that the CDC_Transmit_FS(...) returns USBD_OK only once, and next calls give USBD_Busy.
The MX_USB_DEVICE_Init() looks as follow:
void MX_USB_DEVICE_Init(void)
{
USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS);
USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC);
USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS);
USBD_Start(&hUsbDeviceFS);
USBD_CDC_Init (&hUsbDeviceFS, &USBD_CDC); // I need to init it somewhere so I think here is a good place
}
The CDC_Transmit_FS looks like that:
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
CDC_Init_FS();
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
CDC_Init_FS();
/* USER CODE END 7 */
return result;
}
Does anyone know how to make it running? What do I miss?
Best,
This part look suspicious:
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
CDC_Init_FS();
The call to CDC_Init_FS() probably kills the packet before it had a chance to be sent to the host.
SO... I found the solution!
I can confirm that the code above works (just remove the CDC_Init_FS)!
Acctully, it was a driver problem. for windows 10 you also need to install it despide what's written in the reference

stm32L476RG - how to execute the bootloader from firmware

I am working on a NUCLEO-L476RG board, trying to start the bootloader from my firmware code but its not working for me. here is the code that i am trying to execute :
#include "stm32l4xx.h"
#include "stm32l4xx_nucleo.h"
#include "core_cm4.h"
#include "stm32l4xx_hal_uart.h"
GPIO_InitTypeDef GPIO_InitStructure;
UART_HandleTypeDef UartHandle;
UART_InitTypeDef UART_InitStructre;
void BootLoaderInit(uint32_t BootLoaderStatus){
void (*SysMemBootJump)(void) = (void (*)(void)) (*((uint32_t *) 0x1FFF0004));
if(BootLoaderStatus == 1) {
HAL_DeInit(); // shut down running tasks
// Reset the SysTick Timer
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL =0;
__set_PRIMASK(1); // Disable interrupts
__set_MSP((uint32_t*) 0x20001000);
SysMemBootJump();
}
}
int main(void)
{
HAL_Init();
__GPIOC_CLK_ENABLE();
GPIO_InitStructure.Pin = GPIO_PIN_13;
GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
GPIO_InitStructure.Pull = GPIO_PULLUP;
GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
while (1) {
if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13)) {
BootLoaderInit(1);
}
}
return 0;
}
What i hope to get after the execution of the firmware is that i can connect to the board with a UART and send commands/get responses from the bootloader. the commands i am trying to use come from here: USART protocol used in the STM32 bootloader.
I don't see and response from the board after connecting with the UART.
Here are some ideas taken from the answers to this question.
HAL_RCC_DeInit();
This is apparently needed to put the clocks back into the state after reset, as the bootloader expects them to be.
__HAL_REMAPMEMORY_SYSTEMFLASH();
Maps the system bootloader to address 0x00000000
__ASM volatile ("movs r3, #0\nldr r3, [r3, #0]\nMSR msp, r3\n" : : : "r3", "sp");
Set the stack pointer from bootloader ROM. Where does your 0x20001000 come from? If it's an arbitrary value, then the stack can clobber the bootloader's variables.
Then there is this alternate solution:
When I want to jump to the bootloader, I write a byte in one of the
backup register and then issue a soft-reset. Then, when the processor
will restart, at the very beginning of the program, it will read this
register.
Note that you need LSI or LSE clock for accessing the backup registers.
Try to avoid using __set_MSP(), as current implementation of this function does NOT allow you to change MSP if it is also the stack pointer which you currently use (and you most likely are). The reason is that this function marks "sp" as clobbered register, so it will be saved before and restored afterwards.
See here - STM32L073RZ (rev Z) IAP jump to bootloader (system memory)
Find your bootloader start address from the reference manual.
Then use the following code.
Make sure you have cleaned and disabled the interrupts before do so.
/* Jump to different address */
JumpAddress = *(__IO uint32_t*) (BootloaderAddress + 4);
Jump_To_Application = (pFunction) JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) ApplicationAddress);
Jump_To_Application();
Please have a look at Official STM32 AppNote as well.

Cortex M-0: Simple external interrupt

I'm trying to set up an external interrupt on my LPC812 uC. I've made the following code
#include "LPC8xx.h"
#define RLED 7 // red LED
bool pause = false;
void PININT0_IRQHandler(void)
{
pause = !pause;
}
int main(void) {
LPC_GPIO_PORT->DIR0 |= 1<<RLED; // set pin as output
LPC_GPIO_PORT->SET0 = 1<<RLED;
NVIC_EnableIRQ(PININT0_IRQn);
while (1)
{
if(!pause)
{
LPC_GPIO_PORT->CLR0 = 1<<RLED;
}
}
}
But it isn't working. Am I missing something?
I'm not familiar with NXP MCUs.
But at least place break piont inside PININT0_IRQHandler, to understand clearly that interrupt is not generated.
Also it will be nice to clear interrupt flag inside handler.
Some peripherals need interrupt permission in peripheral registers in addition to NVIC setup.
Did you setup input pin somewhere?
Your code only initialize GPIO 7 pin as output.