Configure PIC port for input and output - io

I'm trying to use two pins of Port A on my PIC18F4620, with one as an output and the other as an input. I've written a simple program that should do this. However, when I debug the program on my board, the output doesn't change according to the input.
I understand why it would be necessary to change the pin configuration every time if I was only using one pin, but the fact that I'm using two different pins (A0 and A1) has me confused. Also, the output does change when I use two different ports (ex. A0 and D1).
Am I missing something, or is this a limitation I have to work around in my design?
Here is the code:
#include <xc.h>
#include "config.h"
void main(void){
TRISAbits.RA0 = 1;
TRISAbits.RA1 = 0;
while(1){
if(PORTAbits.RA0 == 1){
LATAbits.LA1 = 0;
}
else{
LATAbits.LA1 = 1;
}
}
}

Port A on the PIC18F4620 is multiplexed with the analog/digital converter, so you have to configure some settings before being able to use Port A as digital I/O. Take a look at page 91 of the datasheet:
http://ww1.microchip.com/downloads/en/DeviceDoc/39626e.pdf
And change your code to the following:
#include <xc.h>
#include "config.h"
void main(void){
ADCON1 = 0x0F; // Configure A/D for digital input/output on all pins
CMCON = 0x07; // Configure comparator for digital input/output
TRISAbits.RA0 = 1;
TRISAbits.RA1 = 0;
while(1){
if(PORTAbits.RA0 == 1){
LATAbits.LA1 = 0;
}
else{
LATAbits.LA1 = 1;
}
}
}

Related

Software serial using ESP8266

I am transmitting the CSV file saved on SD card using STM32F103 on UART line to ESP8266, The file reading and UART transmission snippet is as below.
While loop of the STM32f103 for read/transmit file.
Using the Software Serial code on ESP8266 code I can read the transmitted string from the STM32F103 and the actual length of the transmitted string is 59 but I am getting following output on the Serial monitor
ESP8266 serial monitor output
The code for Software is as follows
#include <SoftwareSerial.h>
#include <Arduino.h>
#include <stdio.h>
#include <string.h>
using namespace std;
SoftwareSerial s; //RX TX
String str= "";
String str_tx = "";
char char_array[60];
double buff[24];
int str_len = 0;
double val;
char* token;
//char* rest = char_array;
int i=0;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
s.begin(115200, SWSERIAL_8N1, 13, 15, false, 128); //115200, SWSERIAL_8N1, 13, 15, false, 512
pinMode(13, INPUT);
pinMode(15, OUTPUT);
Serial.println("in setup 1");
Serial.println("in setup 2");
Serial.println("in setup 3");
}
void loop() {
// put your main code here, to run repeatedly:2
while(s.available() >0)
{
char ch=s.read();
if(ch != '\n')
str.concat(ch);
if( ch =='\n' )
{
/*Serial.println("------------------------------------");
Serial.println(char_array);
Serial.println("------------------------------------");*/
Serial.println(str);
str_len = str.length();
Serial.println(str_len);
str.toCharArray(char_array, str_len);
Serial.println(char_array);
//strcpy(char_array, str.c_str());
memset(char_array, 0, sizeof(char_array));
str="";
//break;
}
/*
str = s.readStringUntil('\n');
Serial.println(str);
str_len = str.length();
Serial.println(str_len);
//Serial.println(str.c_str());
//strcpy(char_array, str.c_str());
//str.toCharArray(char_array, str_len);
//Serial.println(char_array);*/
}
}
I have used the above code for the reading but the length is showing different after the 1st string which goes around 125 and because of that first time its getting copied into char buffer but further its showing empty.
Would appreciate if anyone could throw some light on what's causing this issue and how to solve it, Thankyou!
Software serial does not work very well on ESP8266. Use lower bitrate. It may be helpful but does not completely solve the problem. I had the same problem using GSM modules.
I used the hardware serial (Serial pin 1 , 3) for this communication and used a software serial to print out the debug information. It make it really hard to work with; because the port is used for programming; you need to add 470R resistor to prevent any damage to your module. Every time you change the code, you need to connect the programmer, program the module then you need to remove the programmer so the board can communicate with your STM32. But using the hardware serial was very stable and solved my problem.

Pm_Read() can't read VMPK input

I have this problem:
i want to create a midi synthesizer in C,linux. Since I don't have a USB midi keyboard, I thought about using a virtual midi divice like VMPK. I found this code in a book that also explained how to use the portmidi library:
#include <stdio.h>
#include <portmidi.h>
#include <porttime.h>
int main() {
int cnt,i,dev;
PmError retval;
const PmDeviceInfo *info;
PmEvent msg[32];
PortMidiStream *mstream;
Pm_Initialize();
cnt = Pm_CountDevices();
if(cnt) {
for(i=0; i < cnt; i++){
info = Pm_GetDeviceInfo(i);
if(info->input)
printf("%d: %s \n", i, info->name);
}
printf("choose device: ");
scanf("%d", &dev);
Pt_Start(1, NULL, NULL);
retval = Pm_OpenInput(&mstream, dev, NULL, 512L, NULL,NULL);
if(retval != pmNoError)
printf("error: %s \n", Pm_GetErrorText(retval));
else {
while(Pt_Time(NULL) < 60000){
if(Pm_Poll(mstream)) {
cnt = Pm_Read(mstream, msg, 32);
for(i=0; i<cnt; i++) {
printf("status:%d, byte1=%d, "
"byte2=%d, time=%.3f\n",
Pm_MessageStatus(msg[i].message),
Pm_MessageData1(msg[i].message),
Pm_MessageData2(msg[i].message),
msg[i].timestamp/1000.);
}
}
}
}
Pm_Close(mstream);
}
}
else printf("No MIDI devices found\n");
Pm_Terminate();
return 0;
}
In short, once the program connects with a MIDI input device, it listens for 60 all the messages that come from them, (Printing the status byte and the two data bytes, as a midi protocol)
When I launch VMPK, it appears that the program reveals VMPK as midi input, under the name "out"
Program output
I also checked the "JACK audio connection" program to verify that VMPK was revealed as a MIDI input device
JACK audio output
I don't understand why when I press a key from the VMPK keyboard, I don't receive any messages from the program ...
I tried to change the VMPK configuration, but I didn't get any changes.
VMPK configuration menu
Maybe I'm doing something wrong in the VMPK configuration.
Any help is welcome.
I thank you in advance for your availability
ok, I found the problem. As I said, I set VMPK badly. If you set it this way, you can detect MIDI inputs
This is the output of programm:

Windows application using libusb: runtime error due to mutex lock

I am trying to establish communication between a laptop and an embedded board over USB. USB driver for board has been installed and it has been detected in Windows device manager. Now I am developing code in Visual Studio 2013 (Win32 Console Application) using libusb.
The libusb_init() function does not return an error however when I try to open the device with libusb_open_device_with_vid_pid(), execution breaks at function usbi_mutex_init() in the threads_windows.c file of the libusb library. This file contains the source for "libusb synchronization on Microsoft Windows".
I also tried to call function libusb_get_device_list() but get the same error. Could you please suggest a solution?
main.cpp from my application source code -->
#include <iostream>
#include "libusb.h"
using namespace std;
int main()
{
int init_status = 0;
libusb_context *context = NULL;
libusb_device_handle *device;
init_status = libusb_init(&context);
if (init_status<0)
{
cout << "could not initialize";
return -1;
}
device = libusb_open_device_with_vid_pid(NULL, 0x0483, 0x5750); //execution breaks here
if (device == NULL)
{
cout << "could not open device";
return -1;
}
else
{
cout << "Device opened successfukky";
}
return 0;
}
threads_windows.c from libusb source code -->
int usbi_mutex_lock(usbi_mutex_t *mutex) {
DWORD result;
if(!mutex) return ((errno=EINVAL));
result = WaitForSingleObject(*mutex, INFINITE); //execution breaks here
if(result == WAIT_OBJECT_0 || result == WAIT_ABANDONED)
return 0; // acquired (ToDo: check that abandoned is ok)
return ((errno=EINVAL)); // don't know how this would happen
// so don't know proper errno
}
Looks to me like you get a specific, non-default context with your libusb_init() but when you use libusb_open_device_with_vid_pid() you are pass NULL which means to use the default context rather than the context created by the libusb_init().
You may just want to use the default context if it is a single device and you only need a single session. The documentation indicates that there are "limitations" with libusb_open_device_with_vid_pid() and it is not intended for anything other than test applications. I assume this is because in real applications there may be multiple devices and this convenience function just takes the first one matching the arguments. However the issue you are seeing is probably related to the context.
For a one off type of specific project your code would look something like:
#include <iostream>
#include "libusb.h"
using namespace std;
int main()
{
int init_status = 0;
libusb_device_handle *device;
// specify NULL for the context address so that libusb_init will use default content.
// this means that any libusb function with a context argument will be called with NULL.
init_status = libusb_init (NULL);
if (init_status < 0)
{
cout << "could not initialize";
return -1;
}
// open the first device found in the device list with this vendor id and product id
// for a real application in a multi-device environment we would need to
// iterate through the various devices using libusb_get_device_list() to get
// the list of devices then using libusb_get_device_descriptor() to iterate
// through the list to find the device we want. also need libusb_free_device_list ()
// after finishing with the list. lots of work for a simple one off project
device = libusb_open_device_with_vid_pid (NULL, 0x0483, 0x5750);
if (device == NULL)
{
cout << "could not open device";
return -1;
} else {
cout << "Device opened successfully";
}
return 0;
}

Uinput and Raspberry Pi

I tried to ask this question on the Raspberry Pi forums, but I have received no responses at all. I thought I might query the minds of the StackOverflow community that has been so helpful in the past.
I'm writing a userspace driver for the Raspberry Pi (specifically, may be ported to other platforms later) which makes use of the bcm2835 library (GPIO) and uinput (Linux user-input virtual devices). I need to read GPIO pins and translate their values into simulated keypresses on a virtual keyboard. The GPIO part has been completed, and the translation part is also completed. Unfortunately, the virtual-keyboard part has not been solved. Uinput refuses to cooperate.
Now, the exact same code works perfectly on a Debian desktop machine. The evdev and uinput modules are required, both of which were loaded in all test cases. On the desktop, inputs can be triggered, however, on the Raspberry Pi, I can verify that the GPIO subsystem has registered the input, but the uinput events do not trigger. Does anyone have a lead on what I might do?
Thank you very much, if you need any information, logs, or otherwise, please let me know and I will post them as soon as I can.
This is a complete solution that works for me. I have a custom-made keypad and these are the keys I have defined. Here is the link to original pdf I used.
Of course you can define whatever key you want, just add it to the array.
Note: this code only works with elevated permission.
int allowed_keys[allowed_KEYS_size][2] = {0};
void main()
{
init_keys();
int fd = open_uinput();
int key_evt = getKeyEVT(49); // ASCII code for 1
// simulate key press and key release
emit(fd, EV_KEY, key_evt, 1);
emit(fd, EV_SYN, SYN_REPORT, 0);
emit(fd, EV_KEY, key_evt, 0);
emit(fd, EV_SYN, SYN_REPORT, 0);
}
long int emit(int fd, int type, int code, int val)
{
struct input_event ie;
ie.type = type;
ie.code = code;
ie.value = val;
/* timestamp values below are ignored */
ie.time.tv_sec = 0;
ie.time.tv_usec = 0;
long int y = write(fd, &ie, sizeof(ie));
return y;
}
int open_uinput()
{
int fdui = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
if (fdui < 0)
{
printf("uinput fd creation failed!\n");
exit(EXIT_FAILURE);
}
ioctl(fdui, UI_SET_EVBIT, EV_KEY);
ioctl(fdui, UI_SET_EVBIT, EV_SYN); //added by behzad
for (int i = 0; i < allowed_KEYS_size; i++)
ioctl(fdui, UI_SET_KEYBIT, allowed_keys[i][1]);
struct uinput_setup usetup;
memset(&usetup, 0, sizeof(usetup));
usetup.id.bustype = BUS_USB;
usetup.id.vendor = 0x1234; /* sample vendor */
usetup.id.product = 0x5678; /* sample product */
strcpy(usetup.name, "My Keypad. Ver 1.1");
ioctl(fdui, UI_DEV_SETUP, &usetup);
ioctl(fdui, UI_DEV_CREATE);
sleep(2);
return fdui;
}
int getKeyEVT(int k)
{
for (int i = 0; i < allowed_KEYS_size; i++)
{
if (allowed_keys[i][0] == k)
return allowed_keys[i][1];
}
return -1;
}
void init_keys()
{
// Reference:
// https://www.alt-codes.net/arrow_alt_codes.php
// /usr/include/linux/input-event-codes.h
allowed_keys[0][0] = 48; //ASCII ---> 0
allowed_keys[0][1] = KEY_0; //LINUX
allowed_keys[1][0] = 49; //ASCII
allowed_keys[1][1] = KEY_1; //LINUX
allowed_keys[2][0] = 50; //ASCII
allowed_keys[2][1] = KEY_2; //LINUX
allowed_keys[3][0] = 51; //ASCII
allowed_keys[3][1] = KEY_3; //LINUX
}

PIC18F String to Bluetooth to Tera Term

I am trying to output a string from the PIC's USART and have it display on Tera Term. I am using the:
PIC18F4331
Sparkfun Bluesmirf RN-42
MPLAB v8.85
Tera Term
I've been working at this code for a couple of days and I am not seeing a single response. A couple of things that I think may be causing the issue is the baud rate and/or not having an interrupt routine. But is there a need for an interrupt if I am only attempting to transmit? Please, can someone guide me? Also, when using printf, I am seeing a response through the bluetooth but in strange symbolic form. For example, รพรพรพ.
The code is a modification of one found online.
// Libraries
#include <p18f4331.h>
#include <stdio.h>
// Configuations
#pragma config OSC = XT
#pragma config WDTEN = OFF
#pragma config PWRTEN = OFF
#pragma config FCMEN = OFF
#pragma config IESO = OFF
#pragma config BOREN = ON
#pragma config BORV = 27
#pragma config WDPS = 128
#pragma config T1OSCMX = ON
#pragma config PWMPIN = ON
#pragma config MCLRE = ON
#pragma config LVP = OFF
#pragma config STVREN = OFF
#pragma config PWM4MX = RD5
// Definitions
#define _XTAL_FREQ 4000000
#define BAUDRATE 9600
void EUSART(void)
{
TRISC = 0b10000000;
SPBRG = 25;
TXSTAbits.CSRC = 0; // Baud Rate Generated Externally
TXSTAbits.TX9 = 0; // 8-Bit Transmission
TXSTAbits.TXEN = 1; // Transmit Enabled
TXSTAbits.SYNC = 0; // Asynchronous Mode
TXSTAbits.BRGH = 1; // High Baud Rate
TXSTAbits.TRMT = 0; // Transmit Shift Register When TSR Is Full
RCSTAbits.SPEN = 1; // Serial Port Enabled
RCSTAbits.RX9 = 0; // 8-Bit Reception
RCSTAbits.CREN = 1; // Enables Receive
}
void SendByteSerially(unsigned char Byte) // Writes a character to the serial port
{
while(!PIR1bits.TXIF) ; // wait for previous transmission to finish
TXREG = Byte;
}
unsigned char ReceiveByteSerially(void) // Reads a character from the serial port
{
while(!PIR1bits.RCIF) continue; // Wait for transmission to receive
return RCREG;
}
void SendStringSerially(const rom unsigned char* st)
{
while(*st) SendByteSerially(*st++);
}
void delayMS(unsigned int x)
{
unsigned char y;
for(;x > 0; x--) for(y=0; y< 82;y++);
}
void main(void)
{
unsigned char SerialData;
EUSART();
SendStringSerially("Hello World");
while(1)
{
SerialData = ReceiveByteSerially();
SendByteSerially(SerialData);
delayMS(1000);
}
}
You are using a PIC18, be sure that BRG16 equals 0 since you're using BRGH
BAUDCTL.BRG16 = 0;
because SPBRGH16 is the higher byte of SPBRG, and that may change the baudrate value of your USART.
Plus, be sure you're in the PIR1 bank. In MPLAB, that would be
banksel PIR1; //Not sure if there's an ending coma
My two functions to transmit via UART when properly initialized ( In MikroC ) :
void vTx232 (UC ucSend)
{
STATUS.RP0 = PIR1; //Sure we're in PIR1
while (PIR1.TXIF == 0);//While last TX not done
TXREG = ucSend; //Input param into TXREG
}
void vTxString(UC *ucpString)
{
while (*ucpString!= 0x00) //While string not at its end
{
vTx232(*ucpString); //Send string character
ucpString++; //Increm string pointer
}
}

Resources