I want to know how exactly do read modify write instructions on PORTx work and why do they cause problems. I used pic12f683 earlier and I don't remember having any issues while writing to GPIO. Why do some examples work while others don't?
//works
while(1) {
LATA++;
Delay_ms(1000);
}
//works
char i = 0;
while(1) {
PORTA = i++;
Delay_ms(1000);
}
//doesn't work
while(1) {
PORTA++;
Delay_ms(1000);
}
//doesn't work
char i = 0;
while(1) {
i = PORTA;
PORTA = i++;
Delay_ms(1000);
}
//doesn't work either for some reason (PORTA seems to be read as 0 always)
char i = 0;
while(1) {
i = PORTA;
LATA = i++;
Delay_ms(1000);
}
//neither does this one
char i = 0;
while(1) {
i = LATA;
LATA = i++;
Delay_ms(1000);
}
Section 10 of pic18f4550 datasheet says:
Reading the PORTA register reads the status of the pins; writing to it
will write to the port latch.
Doesn't it mean that writing to PORTA is the same as writing to LATA (port latch ...or is it)?
Here is the picture in case it helps with the explanation.
Reading the PORTA register reads the status of the pins; writing to it
will write to the port latch.
As stated above, it means that what you want to write will always be written in a LAT (latch register), but it doesn't mean that it will be the state of the port output. For example it is possible that you have wrong TRIS configuration (set port or IO pin as an input), or you have hardware malfunction which pulls pin low or high, etc. All this means that you can write to the port (LAT) but the result that you will read doesn't have to be the same as one you wrote.
Reading from the port will always return the current (physical) state of these lines no matter what is in LAT.
Related
I have arduino with code below. It has encoder, and prints something on encoder turn. But also it receive a lot of data, so if arduino is reading serial main loop stops and encoder loosing steps. How can I write code where encoders printing has always priority?
code:
#include <Encoder.h>
String receivedData = "";
Encoder encoder1(24, 25);
long position1 = -999;
long newPosition1;
void setup() {
Serial.begin(57600);
}
void loop() {
newPosition1 = encoder1.read();
if (newPosition1 != position1) {
Serial.print("PrintSomething");
}
position1 = newPosition1;
Serial.flush();
if(Serial.available() > 0) {
receivedData = Serial.readStringUntil(';');
if (receivedData == "?") {
Serial.print("3," + String(deviceId) + ",0,0,3;");
}
doSomethingImmediatly();
}
}
Important thing is in reality i have 6 encoders, so i can't use interrupts. And doSomethingImmediatly function should run as fast as possible.
Funny thing is if i use higher braud the problem is even more visible.
I would strongly suggest using SerialEvent instead of polling for serial data. This way, you build the serial string char by char and you can decide where to stop reading.
I would rather poll the encoders to avoid using clock cycles reading the status of every encoder sequentially. Otherwise, reconsider using a different library that might offer better performance (like RotaryEncoder from mathertel)
Based on the number of encoders that you are trying to read and the potential bottlenecks that you will encounter at 16 MHz (most common clock speed from Arduino - unless us Due or Mega-), I advise porting your application to a Teensy Microcontroller (> 3.2)
Keep in mind, there is no such thing as 'priorities' unless, as lurker mentioned, you use RTOS. You have to play with timings and efficient logic
For instance, a skimmed example code would look like the following (it shows only one polling routine):
unsigned long previousEncoderTime;
unsigned long pollPeriod = 200; // Poll every 200 ms
char serialString[] = " "; // Empty serial string variable
bool stringFinished = false; // Flag to indicate reception of a string after terminator is reached
void setup(){
previousEncoderTime = 0;
}
void loop(){
unsigned long now = millis();
if (now - previousEncoderTime >= pollPeriod){
previousEncoderTime = now;
// Encoder reading routine
}
if (stringFinished){ // When the serial Port has received a command
stringFinished = false;
// Implement your logic here
}
}
void serialEvent()
{
int idx = 0;
while (Serial.available())
{
char inChar = (char)Serial.read();
if (inChar == '\n') // The reading event stops at a new line character
{
serialTail = true;
serialString[idx] = inChar;
}
if (!serialTail)
{
serialString[idx] = inChar;
idx++;
}
if (serialTail)
{
stringFinished = true;
Serial.flush();
serialTail = false;
}
}
}
I have a strange problem with trying to write data to a serial port.
I am running Ubuntu 16.04 on a NUC7i7DNBE, and am trying to make a serial connection to an Arduino UNO. The Serial API that I am using is found here: http://docs.ros.org/kinetic/api/serial/html/classserial_1_1Serial.html
I have written a simple program which opens the serial port "ttyACM0" to communicate with the arduino. I have tested this code on another computer running Ubuntu 16.04, and everything worked fine, the only permissions I had to set where adding the user to the dialout group.
On the NUC, however, I have added the user to the dialout group. This allowed the program to read from the Arduino, but it still does not write to the Arduino. The Arduino IDE will write to the Arduino just fine, but my program will not.
I am assuming that I am having trouble with serial write permissions in Ubuntu.
Steps I have taken:
I have added the user to the dialout group
I have added a rule in /etc/udev/rules.d/ which states:
SUBSYSTEMS=="tty", GROUP="dialout", MODE="0666"
Afterward, I sent the commands:
sudo chown root:root /etc/udev/rules.d/50-AVCusb.rules
sudo chmod 0644 /etc/udev/rules.d/50-AVCusb.rules
udevadm control --reload-rules
I followed some information found on stack exchange to get to this point:
https://unix.stackexchange.com/questions/111593/allow-non-root-user-to-read-write-dev-files
I have tried using an FTDI device to write to the Arduino port. The FTDI device uses the ttyUSB0 port rather than the ttyACM0 port. The result was the same; can read, but can't write.
I have also run my external hard-drive on the NUC to see if there was any kind of hardware issue. When I ran the program from my external hard drive, I had no problem reading from and writing to the Arduino.
I have not dealt much with Ubuntu permissions or ports in general, please help me find and upload any other information that you may need in order to help me solve this problem.
Code on NUC:
#include <ros/ros.h>
#include <serial/serial.h>
using namespace serial;
Serial ser;
static const uint8_t MOTOR_ID = 0;
void writeMotor(uint8_t byte)
{
size_t size = 4;
uint8_t buffer[size];
buffer[0] = 'G'; //PID
buffer[1] = 'O';
buffer[2] = MOTOR_ID; //address
buffer[3] = byte; //data byte
ser.write(buffer, size);
}
int main() {
ros::init(argc, argv, "servo_esc_driver");
std::string port = "/dev/ttyACM0";
Timeout timeout = Timeout(0, 0, 0, 0, 0);
bytesize_t bytesize = eightbits;
parity_t parity = parity_none;
stopbits_t stopbits = stopbits_one;
flowcontrol_t flowcontrol = flowcontrol_none;
try{
ser.setPort(port);
ser.setBaudrate(115200);
ser.setTimeout(timeout);
ser.setBytesize(bytesize);
ser.setParity(parity);
ser.setStopbits(stopbits);
ser.setFlowcontrol(flowcontrol);
ser.open();
}
catch (SerialException e) {
ROS_FATAL_NAMED("Failed to connect to the Arduino UNO, %s.", e.what());
ros::shutdown();
return 0;
}
uint8_t byte = 90;
writeMotor(byte);
}
Full Code on Arduino
#include <Servo.h>
const byte N = 2;
//Servo esc;
//Servo servo;
Servo servo[N];
//int escPos = 90;
//int servoPos = 90;
int pos[N];
static const byte ESC_PIN = 7;
static const byte SERVO_PIN = 8;
static const byte RPM_FEEDBACK_PIN = 0; //interrpt 0, pin 2
static const byte SERVO_FEEDBACK_PIN = A0;
//const float MUL = 0.7058823529; //180/255
unsigned long lastTime_servoFeedback = 0;
static const byte MOTOR_ID = 0; //ID for differentiating data received and sent over serial connections
static const byte SERVO_ID = 1;
//added for motor data timeout safety feature
static const unsigned long MOTOR_DATA_TIMEOUT = 200; //4 x 50 ms (50 ms time period expected)
static unsigned long lastTimeMotorData = 0;
static const byte NEUTRAL = 90;
unsigned long last_rpm_pulse_update_ms = 0; //used for detecting a stopped car, and rejecting old data when writing to the serial port
unsigned long last_rpm_pulse_time_us = 0;//keeps track of rpms by comparing to system timer
static const long REV_PERIOD_MAX_US = 100000; //in us
unsigned long rev_period = REV_PERIOD_MAX_US; //100 ms is considered too long to be in motion
boolean forward = true;
/*Scratch that, I want these parameters set in ROS:
static const float wheel_radius = 0.05 // meters
static const float revs_to_mps_MUL = //assuming 2.85 gear ratio for brushless motor differential: https://forums.traxxas.com/showthread.php?9080733-Diff-gear-ratios
*/
//boolean rpm_period_updated = false; //rpms must be updated every 100 ms, otherwise the car has stopped, and velocity data should show 0 m/s
void rpm_feedback()
{
//Serial.println("in rpm_feedback");
last_rpm_pulse_update_ms = millis(); //notice the 'ms' here we want to use millisecond for checking whether or not data is valid. millis() can count up to 50 days while micros() only counts up to 70 minutes, thus millis() is used here.
unsigned long time_now = micros(); //use time now for accurate time calculations
unsigned long rev_period_temp = time_now - last_rpm_pulse_time_us; //get spur-gear revolution period
if(rev_period_temp > 0) rev_period = rev_period_temp; //revs are within
else rev_period = REV_PERIOD_MAX_US;
last_rpm_pulse_time_us = time_now; //using 'time_now' ensures that the time taken to get to this point in code does not interfere with rev_period accuracy - - - micros(); //reset time
if(pos[MOTOR_ID] < 90) //determine the direction that the vehicle is traveling in
{
forward = false;
}else forward = true;
//rpm_period_updated = true; not needed, only last_rpm_pulse_time_ms is needed for checking
}
void setup() {
// put your setup code here, to run once:
pinMode(RPM_FEEDBACK_PIN, INPUT_PULLUP);
attachInterrupt(RPM_FEEDBACK_PIN, rpm_feedback,FALLING); //arduino reference recommends using digitalPinToInterrupt(RPM_FEEDBACK_PIN) but the command is not recognized here
analogReference(EXTERNAL); //Using external reference for servo position
for(int i = 0; i < N; i++) //initialize
{
pos[i] = 90;
servo[i].attach(ESC_PIN + i);
}
Serial.begin(115200);
}
void loop() {
// put your main code here, to run repeatedly:
if(Serial.available() >= 1)
{
if(Serial.read() == 'G')
{
unsigned long t = millis();
while((Serial.available() < 3) && ((millis() - t) < 10)); //wait for the rest of the package, or timeout
if(Serial.available() >= 3)
{
char buf[3];
Serial.readBytes(buf, 3);
if((buf[0] == 'O') && (buf[1] >= 0) && (buf[1] < 2))
{
pos[buf[1]] = byte(buf[2]);
if(buf[1] == MOTOR_ID) lastTimeMotorData = millis(); //time stamp of last motor data retrieval
//Serial.print("buf[2]: ");
//Serial.println(byte(buf[2]), DEC);
//Serial.print("pos: ");
//Serial.println(pos[buf[1]]);
}
}
}
}
if((millis() - lastTimeMotorData) > MOTOR_DATA_TIMEOUT) pos[MOTOR_ID] = NEUTRAL; //stop the motor if data is not being received
for(int i = 0; i < N; i++)
{
servo[i].write(pos[i]);
}
if((millis() - lastTime_servoFeedback) >= 50) // 20Hz 20) //50Hz matches current ROS driver settings
{
lastTime_servoFeedback = millis();
int servo_feedback = analogRead(SERVO_FEEDBACK_PIN);
Serial.write('G'); //PID
Serial.write('O');
Serial.write(SERVO_ID);
//Serial.print(servo_feedback);
Serial.write(lowByte(servo_feedback));
Serial.write(highByte(servo_feedback));
//Serial.println(servo_feedback);
float rev_frequency;
if((last_rpm_pulse_update_ms + 100) < millis()) rev_frequency = 0; //use millis() since it can count up to 50 days, and will not have a chance of a hiccup after 70 minutes of using micros()
//instead, correct period when slowing down, also stop when the maximum threshold is reached
//if((micros() - last_rpm_pulse_time_us) >= REV_PERIOD_MAX_US) rev_frequency = 0; //car is stopped in this case. I decided not to try correcting the period as mentioned above
else rev_frequency = (float) 1/rev_period*1000000;
byte *rev_freq_bytes_to_transmit = (byte *) &rev_frequency;
if(forward == false) rev_frequency = -rev_frequency; //a negative frequency is used for reverse
Serial.write('G'); //PID
Serial.write('O');
Serial.write(MOTOR_ID); //used for addressing
Serial.write(rev_freq_bytes_to_transmit, 4);
}
}
Some good information may be:
snuc#usuavc:~$ udevadm info -a -n /dev/ttyACM0
Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.
looking at device '/devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4:1.0/tty/ttyACM0':
KERNEL=="ttyACM0"
SUBSYSTEM=="tty"
DRIVER==""
looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4:1.0':
KERNELS=="1-4:1.0"
SUBSYSTEMS=="usb"
DRIVERS=="cdc_acm"
ATTRS{authorized}=="1"
ATTRS{bAlternateSetting}==" 0"
ATTRS{bInterfaceClass}=="02"
ATTRS{bInterfaceNumber}=="00"
ATTRS{bInterfaceProtocol}=="01"
ATTRS{bInterfaceSubClass}=="02"
ATTRS{bNumEndpoints}=="01"
ATTRS{bmCapabilities}=="6"
ATTRS{supports_autosuspend}=="1"
looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-4':
KERNELS=="1-4"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{authorized}=="1"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{bConfigurationValue}=="1"
ATTRS{bDeviceClass}=="02"
ATTRS{bDeviceProtocol}=="00"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bMaxPacketSize0}=="8"
ATTRS{bMaxPower}=="100mA"
ATTRS{bNumConfigurations}=="1"
ATTRS{bNumInterfaces}==" 2"
ATTRS{bcdDevice}=="0001"
ATTRS{bmAttributes}=="c0"
ATTRS{busnum}=="1"
ATTRS{configuration}==""
ATTRS{devnum}=="4"
ATTRS{devpath}=="4"
ATTRS{idProduct}=="0043"
ATTRS{idVendor}=="2341"
ATTRS{ltm_capable}=="no"
ATTRS{manufacturer}=="Arduino (www.arduino.cc)"
ATTRS{maxchild}=="0"
ATTRS{quirks}=="0x0"
ATTRS{removable}=="removable"
ATTRS{serial}=="55330313635351207081"
ATTRS{speed}=="12"
ATTRS{urbnum}=="6990"
ATTRS{version}==" 1.10"
looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1':
KERNELS=="usb1"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{authorized}=="1"
ATTRS{authorized_default}=="1"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{bConfigurationValue}=="1"
ATTRS{bDeviceClass}=="09"
ATTRS{bDeviceProtocol}=="01"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bMaxPacketSize0}=="64"
ATTRS{bMaxPower}=="0mA"
ATTRS{bNumConfigurations}=="1"
ATTRS{bNumInterfaces}==" 1"
ATTRS{bcdDevice}=="0415"
ATTRS{bmAttributes}=="e0"
ATTRS{busnum}=="1"
ATTRS{configuration}==""
ATTRS{devnum}=="1"
ATTRS{devpath}=="0"
ATTRS{idProduct}=="0002"
ATTRS{idVendor}=="1d6b"
ATTRS{interface_authorized_default}=="1"
ATTRS{ltm_capable}=="no"
ATTRS{manufacturer}=="Linux 4.15.0-32-generic xhci-hcd"
ATTRS{maxchild}=="12"
ATTRS{product}=="xHCI Host Controller"
ATTRS{quirks}=="0x0"
ATTRS{removable}=="unknown"
ATTRS{serial}=="0000:00:14.0"
ATTRS{speed}=="480"
ATTRS{urbnum}=="76"
ATTRS{version}==" 2.00"
looking at parent device '/devices/pci0000:00/0000:00:14.0':
KERNELS=="0000:00:14.0"
SUBSYSTEMS=="pci"
DRIVERS=="xhci_hcd"
ATTRS{broken_parity_status}=="0"
ATTRS{class}=="0x0c0330"
ATTRS{consistent_dma_mask_bits}=="64"
ATTRS{d3cold_allowed}=="1"
ATTRS{dbc}=="disabled"
ATTRS{device}=="0x9d2f"
ATTRS{dma_mask_bits}=="64"
ATTRS{driver_override}=="(null)"
ATTRS{enable}=="1"
ATTRS{irq}=="122"
ATTRS{local_cpulist}=="0-7"
ATTRS{local_cpus}=="ff"
ATTRS{msi_bus}=="1"
ATTRS{numa_node}=="-1"
ATTRS{revision}=="0x21"
ATTRS{subsystem_device}=="0x2070"
ATTRS{subsystem_vendor}=="0x8086"
ATTRS{vendor}=="0x8086"
looking at parent device '/devices/pci0000:00':
KERNELS=="pci0000:00"
SUBSYSTEMS==""
DRIVERS==""
I decided that the problem was with the ROS version of serial. I decided to try some native linux library, termios, and had success writing to the port!
I found this example code:
https://en.wikibooks.org/wiki/Serial_Programming/Serial_Linux
The problem lies in the ros serial installation somehow.
Don't know if you still want to solve this with serial/serial.h, but I think that your problem might be in the timeout settings.
I'm telling you this, 'cause I had the exact same problem, I could read the incoming data, but couldn't write.
The /dev/ttyUSB0 permission was ok, but not the timeout.
I found the following config on internet, gave a try and work. Now I can read and write.
try{
ser.setPort("/dev/ttyUSB0");
ser.setBaudrate(9600);
serial::Timeout to = serial::Timeout::simpleTimeout(10);
ser.setTimeout(to);
ser.open();
return true;
}
catch (SerialException e) {
return 0;
I am trying to configurate my XBee module by an Arduino pro mini that is connected to my computer by de FTDI basic from sparkfun.
I already can write and send data from the Xbee to another Xbee module by the Arduino.
My problem is that I want to configure the Xbee by the arduino. I am sending ‘+++’ with the arduino to my Xbee and want to receive the ‘OK’ from the Xbee with the serial monitor from the arduino editor. The problem is that I can send it but never receive and ‘OK’, and when I am trying to configure the Xbee the configuration never happened. So I cant reach the Xbee command line.
uint8_t pinRx = 0, pinTx = 1; //Initialise pins on the Arduino
char GotChar;
long BaudRate = 4800;
int incomingByte=0;
SoftwareSerial mySerial( pinRx , pinTx ); //Initialise SoftwareSerial
void init_USB()
{
Serial.begin(BaudRate);
Serial.println("Start");
mySerial.begin(BaudRate);
}
void init_XBee()
{
Serial.begin(9600);
int check = 0;
while(T_XBEE_CONTROLLER_CheckOK() == 0)
{
Serial.println("CheckOK");
Serial.write("+++");
delay(2000);
}
Serial.println("ATCH 8\r");
delay(2000);
Serial.write("ATID 1234\r");
delay(2000);
Serial.write("+++");
delay(2000);
Serial.write("ATPL 0\r");
delay(2000);
Serial.write("+++");
delay(2000);
Serial.write("ATAP 2\r");
delay(2000);
}
int T_XBEE_CONTROLLER_CheckOK()
{
char ch[2];
ch[0] = 0x00;
while(! ((ch[0] == 'O' ) && (ch[1] == 'K') ))
{
ch[0] = mySerial.read();
ch[1] = mySerial.read();
if((ch[0] != 'O') && (ch[1] != 'K') && (ch[2] != '\r'))
{
Serial.println("FAILED");
return 0;
}
Serial.println("SUCCES");
return 1;
}
return 0;
}
it is a stupid answer but first of all, you should check that your Xbee is configured as AT device instead of API device. If it is API mode, the module wont understand the messages.
To do that you just have to use X-CTU application and read the configuration of the module, and change it to AT device.
Hope that helps.
Thanks for the response and the help, and also sorry for the late response.
I already solved the problem. The problem was the function write(). If you want to reach the command mode from the XBee you should only send "+++". If there is some kind of character behind the "+++" you can't reach the command line. The function write put a (for me) unknown character behing the "+++". So that's the problem for not reaching the command line.
To resolve this problem just use the function print("+++"). After using this function it is possible to reach the command line.
You have to read from the serial right after you send the +++ command, because this is where the xbee writes 'OK'. Also a better way to respect the guard times is to wait for a reply, and test to see if it is 'OK'.
Here is my code, I don't remember if it was working the last time I checked but I will just paste it here and you can modify it as you like. All it does is broadcast A1, B2, C3, etc.
There's a lot of commenting out where I was experimenting, but the regular comments are informative. Make sure you go through it step by step, it's quite simple when you get your head around it. Don't forget to change the destination address low to 0xFFFF if you want to broadcast.
In the end you'll come to the same realisation I did that AT mode is not suitable for configuring the xbee by writing programs.
For example I had an xbee constantly transmitting the number '2', and when another xbee was entering command mode using this code, it would receive the number 2 from the remote xbee when it should have received the 'OK' message from the local xbee, thus the program didn't acknowledge it being in command mode and breaking. When entering command mode you'd think an xbee would turn it's receiver off, but that's not the case so you can easily get into trouble.
If you want to do it the right way, have a look at API mode. I have series 1 xbee's so I'm implementing the Digimesh protocol, which so far I haven't seen anyone online do, but it's almost identical to the Zigbee so it's easy. If you'd like I can give you my code for that which can serve as a simple example.
/*
unicast_configure
Configure an XBee for unicast transmission and transmit
some characters to test
*/
#include <SoftwareSerial.h>
// Pins on Bees Shield:
SoftwareSerial xbee(2, 3); // TX, RX
boolean configured;
char c = 'A';
boolean configureRadio() {
// Set the data rate for the SoftwareSerial port:
xbee.begin(9600);
// Put the radio in command mode:
Serial.write("Entering command mode\r");
delay(1000);
while(xbee.available()>0) {xbee.read();}
xbee.write("+++");
while(xbee.available()>0) {xbee.read();}
//delay(1000);
//while(xbee.available() > 0) {Serial.write(xbee.read());}
String ok_response = "OK\r"; // The response we expect
// Read the text of the response into the response variable
// This satisfies the guard time by waiting for the OK message
String response = String("");
while (response.length() < ok_response.length()) {
if (xbee.available() > 0) {
response += (char) xbee.read();
}
}
Serial.println("response1: " + response);
// If we got received OK, configure the XBee and return true:
if (response.equals(ok_response)) {
Serial.println("Enter command mode successful");
// Restore to default values:
Serial.println("Restoring default values before making changes");
xbee.write("ATRE\r");
Serial.println("Setting addr high");
xbee.write("ATDH0\r"); // Destination high
//while(xbee.available() > 0) {Serial.write(xbee.read());}
Serial.println("Setting addr low");
xbee.write("ATDL1\r"); // Destination low-REPLACE THIS
//while(xbee.available() > 0) {Serial.write(xbee.read());}
Serial.println("Setting MY address");
xbee.write("ATMYFFFF\r");
// Apply changes:
Serial.println("Applying changes");
xbee.write("ATAC\r");
/*
///////////////////////////////////////////////
// Write to non-volatile memory:
// Use similar technique as above to satisfy guard time
Serial.write("Saving\r");
xbee.write("ATWR\r");
String response2 = String("");
//while (xbee.available() > 0) {Serial.write(xbee.read());}
while (response2.length() < ok_response.length()) {
if (xbee.available() > 0) {
response2 += (char) xbee.read();
}
}
Serial.println("response2: " + response2);
if (response2.equals(ok_response)) {
Serial.println("Save successful");
}
else { Serial.println("Save not successful");
return false;
}
// And reset module:
Serial.println("Resetting");
xbee.write("ATFR\r");
///////////////////////////////////////////////
*/
Serial.write("Exit command mode\r");
xbee.write("ATCN\r"); // Exit command mode
//while(xbee.available() > 0) {Serial.write(xbee.read());}
Serial.write("Finished\r");
return true;
} else {
return false; // This indicates the response was incorrect
}
}
void setup() {
Serial.begin(9600); // Begin serial
configured = configureRadio();
}
void loop() {
// Test transmission:
if (configured) {
xbee.print(c);
Serial.print(c);
c = c + 1;
if (c > 'Z') { c = 'A'; }
}
else {
Serial.println("Not configured (in loop)");
delay(5000);
Serial.println("Retrying configuration");
configured = configureRadio();
}
delay(1500);
}
I am trying to transmit a character "a" from pic16f887 and see the result on the terminal, but all I get is a question mark(using USART terminal), or nothing at all(Putty, Hyperterminal). I am not so great with C, as I'm only a beginer, but I really need to get this working for my school project.. I have tried many codes I've found over the internet, and I did manage to receive a character from the terminal and, lets say, turn on a LED, but I just can't manage to make it send anything. And I have a strong feeling its somewhere in the code.. Im using MPLAB and Hi-Tech C compiler to build the project. Here it is:
unsigned char cUART_char;
unsigned char cUART_data_flg;
void init_uart(void);
void UART_putc(unsigned char c);
void InterruptHandlerLow ();
void main()
{
TRISA = 0;
PORTA = 0;
TRISB = 0;
PORTB = 0;
TRISD = 0;
PORTD = 0;
ANSELH = 0;
init_uart();
while (1)
{
if (cUART_data_flg==1)
{
UART_putc(cUART_char);
cUART_data_flg=0;
}
}
}
void InterruptHandlerLow ()
{
if (RCIF==1)//is interrupt occured by EUSART receive?,
//then RCREG is full we have new data (cleared when RCREG is read)
{
if(RCSTA&0x06) //more efficient way than following commented method to check for reception error
//if(RCSTAbits.FERR==1 || RCSTAbits.OERR==1 )
{
CREN=0; //Overrun error (can be cleared by clearing bit CREN)
cUART_char=RCREG; //clear Framing error
CREN=1;
}
else
{
cUART_char = RCREG; // read new data into variable
cUART_data_flg = 1; // new data received. so enable flg
}
}
}
void init_uart(void) // init UART module for 9600bps boud, start bit 1, stopbit 1, parity NONE
{
// init data receive flag to zero (no data)
TRISC7=1; //Make UART RX pin input
TRISC6=0; //Make UART TX pin output
SYNC = 0; // enables for asynchronous EUART
SPEN = 1; // enables EUSART and sets TX (RC6) as output; ANSEL must be cleared if shared with analog I/O
CREN = 1;
TX9 = 0; // 8bit mode
RX9 = 0;
TXEN = 1; // enables Transmitter
BRGH = 1; // baud rate select
BRG16 = 0;
SPBRG = 25; //baud rate select 9600#4Mhz
SPBRGH = 0;
RCIE=1; // receive interrupt enable
GIE=1; // global interrupt enable
PEIE=1 ; // Peripheral Interrupt Enable bit
}
void UART_putc(unsigned char c)
{
TXEN=0;// disable transmission
TXREG=0x61; // load txreg with data
TXEN=1; // enable transmission
while(TRMT==0) // wait here till transmit complete
{
}
}
Please if someone sees a problem (or more) in this code, help me to crack this ;)
Oh and I am transmitting when pressing a button connected to a TX pin (RC6)..
Hi i am trying to communicate my 89c52 with sim548c module. I am sending AT commands and then making the microcontroller store all replies in an array and go through a search function to see if proper reply was sent so it can move on to next AT command. This requires two way serial transfer. i have to first send serially the AT command, then enable reception and store all replies from the module in an array. I am using this program but i cant get the microcontroller to accept the incoming data and store it in an array. it transfers successfully but doesnt receive. Can you kindly identify what is the problem?
int check=0;
int out=0;
unsigned char info[20]={"00000000000000000000"};
unsigned char *s;
unsigned char a[3],b[3];
void transmit_data(unsigned char str)
{
SBUF=str;
while(TI==0);
TI=0;
}
void send_serial(unsigned char *s)
{
delay(50);
while(*s!=0x0)
{
SBUF=*s;
while(TI==0)
{
}
TI=0;
s++;
}
}
void receive_data() interrupt 4
{
if(RI)
{
info[check++]=SBUF;
RI=0;
}
if(TI)
TI=0;
}
void search(unsigned char b[])
{
int l=0;
for(l;l<18;l++)
{
if(info[l]==b[0] && info[l+1]==b[1] && info[l+2]==b[2])
{
out=1;
break;
}
}
}
void compare(unsigned char *s, unsigned char a[]) //for CIPSEND
{
while(1)
{
out=0;
check=0;
delay(50);
send_serial("AT+CIPSEND\r");
delay(100);
send_serial(s);
transmit_data(0x0D);
transmit_data(0x0A);
transmit_data(0x1A);
IE=0x90;
delay(200);
IE=0x88;
search(a);
if (out==1)
break;
}
}
i have seen this a couple of times and th mistake is that your serial receive works with an interrupt and it is not a voidable function smply remove the VOID that is attached to INTERRUPT 4 so tha ur code becomes
receive_data() interrupt 4
{
if(RI)
{
info[check++]=SBUF;
RI=0;
}
if(TI)
TI=0;
}
I would suggest making a smaller (as simple as you can) program that does nothing more than receive (by interrupt?) data and blink a LED or echo it back or in some other way indicate that you can reliably receive. Use that to talk to a terminal emulator or another known working interface. Cut out all possible middlemen and unknowns.
Check also UART error registers and configuration to make sure your clock/parity/data settings match in both ends. Start with a slow rate first.
Make one piece at a time work reliably, then put them together.