UART sending wrong characters on pic18 - send

I'm trying to simply send characters trough my UART Interface by calling the funktion: UART_Write_Text("hello");
this is the code executed in the the uart.c file:
void UART_Init(void)
{
//115200bps deafult value for RN4678
BRGH = 0; //Setting High Baud Rat
BRG16 = 0; //8-Bit mode
SPBRG = 8; //Writing SPBRG Register
TXSTAbits.SYNC = 0; //Setting Asynchronous Mode, ie UART
RCSTAbits.SPEN = 1; //Enables Serial Port
RCSTAbits.CREN = 1; //Enables Reception
TXSTAbits.TXEN = 1; //Enables Transmission
}
/******************************************************************************/
//-----UART write byte
/******************************************************************************/
void UART_Write(char data)
{
while(!TRMT);
TXREG = data;
}
/******************************************************************************/
//-----UART check tx queue
/******************************************************************************/
char UART_TX_Empty(void)
{
return TRMT;
}
/******************************************************************************/
//-----UART write string
/******************************************************************************/
void UART_Write_Text(char *text)
{
for(int i=0; text[i]!='\0' || text[i] !=0x00; i++){
UART_Write(text[i]);
}
UART_Write('\n');
}
/******************************************************************************/
//-----UART data ready to read
/******************************************************************************/
char UART_Data_Ready(void)
{
return RCIF;
}
/******************************************************************************/
//-----UART read byte
/******************************************************************************/
char UART_Read(void)
{
while(!RCIF);
return RCREG;
}
/******************************************************************************/
//-----UART read string
/******************************************************************************/
void UART_Read_Text(char *Output, unsigned int length)
{
unsigned int i;
for(int i=0;i<length;i++)
Output[i] = UART_Read();
}
Now when I'm debugging it, I see that it writes the wright charakters into the TXREG. At the end it sended the following characters: 'h', 'e', 'l', 'l', 'o', '\n'.
I send them to the bluetooth module RN4678 with a baud rate of 115200bps which is also the default baud rate of the BT module. However when I read the sended character on my phone with a Bluetooth terminal i get only some characters wright and the other ones are questionmarks, so it doesn't recognise them (not always the same character unrecognised).
I already experimented with the baud rate, but it looks like its the right value I writed into the SPBRG.
I'm also polling the TRMT so there shouldn't be any collisions...
Someone knows what I'm doing wrong?

#include "Configuration_bits.h"
#include <xc.h>
#include <stdio.h>
#include <p18f67k22.h>
#include <string.h>
#include <stdlib.h>
#define _XTAL_FREQ 16000000
void UART_Init_1(){
TRISCbits.TRISC6=1; // TX1 Pin-31
TRISCbits.TRISC7=1; // RX1 Pin-32
RC1IE=1;
SPBRG1=34; // Baud Rate 115200
BAUDCON1bits.BRG16=1;
TXSTA1bits.BRGH=1;
//TXSTA 1 Register
TXSTA1bits.TX9=0; // 8-bit transmission
TXSTA1bits.TXEN=0;
TXSTA1bits.TXEN=1; // Transmit is enabled
TXSTA1bits.SYNC=0; // Asynchronous mode
TXSTA1bits.TRMT=1; // Transmit Shift Register Status bit
//RXSTA 1 Register
RCSTA1bits.SPEN=1; // Serial Port Enable bit
RCSTA1bits.RX9=0; // 8-bit reception
RCSTA1bits.CREN=1; // Continuous Receive Enable bit
}
void UART_Tx_1(unsigned char z[])
{
unsigned int uart_tx1=0;
while(z[uart_tx1]!='\0')
{
while(!TX1IF);
TXREG1=z[uart_tx1];
uart_tx1++;
}
}
void UART_Rx_1()
{
string_rx1[uart_rx1]=RCREG1;
uart_rx1++;
}
void interrupt ISR(void)
{
if(RC1IF && RC1IE) // UART_1
{
}
}
void main(void)
{
System_Initialization();
UART_Init_1();
while(1)
{
UART_Tx_1("HELLO\r\n"); // Transmit Hello
}
}

Related

How can i solve data transferred from slave to master using SPI?

I tried to make a communication between two AVR (ATmega128) using SPI.
Data transferred correctly from master to slave but data transferred wrong from slave to master, the first sampled bit is always wrong.
Slave sends (0X7E) to master but the received data is (0X3F).
Where is the mistake?
Code of MASTER
#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>
#define ACK 0x7E
void spi_init_master(void)
{
DDRB = (1<<0)|(1<<1)|(1<<2); //Set MOSI, SCK, SS as Output
PORTB |= 1;
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0); //Enable SPI, Set as Master, Prescaler: Fosc/16
}
//Function to send and receive data
unsigned char spi_tranceiver(unsigned char data)
{
PORTB &= ~(1<<0);
SPDR = data; //Load data into the buffer
while (!(SPSR & (1<<SPIF) )); //Wait until transmission complete
PORTB |= (1<<0);
return (SPDR); //Return received data
}
int main(void)
{
spi_init_master(); //Initialize SPI Master
unsigned char data;
unsigned char ret;
while (1)
{
ret = spi_tranceiver(data);
}
}
Code of SLAVE
#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>
#define ACK 0x7E
void spi_init_slave(void)
{
DDRB = (1<<3); //MISO as OUTPUT
SPCR = (1<<SPE); //Enable SPI
}
//Function to send and receive data
unsigned char spi_tranceiver(unsigned char data)
{
SPDR = data; //Load data into buffer
while (!(SPSR & (1<<SPIF) )); //Wait until transmission complete
return (SPDR); //Return received data
}
int main(void)
{
spi_init_slave(); //Initialize slave SPI
unsigned char data;
while (1)
{
data = spi_tranceiver(ACK);
}
}
Maybe the problem is at reloading the data register #SLAVE. In your code this is done via polling. So if you have a high clock speed the slave does not get enough time to reload the register corectly.
Important notice:
Clock peed of SPI has to be F_CPU/4 on slave (see the datasheet on Page 168)
Try to put in a delay at master. So the slave got some time to reload the register:
#define F_CPU ?????????UL // Clock speed of system in Hz
unsigned char spi_tranceiver(unsigned char data);
#include <util/delay.h>
int main(void)
{
// ...
while (1)
{
ret = spi_tranceiver(data);
}
}
unsigned char spi_tranceiver(unsigned char data)
{
_delay_ms(10);
PORTB &= ~(1<<SS);
SPDR = data;
while (!(SPSR & (1<<SPIF)));
PORTB |= (1<<SS);
return (SPDR);
}
Try to start the slave before master is started!

ESP8266 Sniffing and sending Mac address

I'm trying to make my ESP8266 sniffing nearby devices, then posting them by with a HTTP request. With purpose is to record when my roommate and I are at home. Then in the future, trigger certain tasks like turning on/off the lights if we're home or not. I don't care at all about the packets content just the mac addresses.
So fare I've found this, script that prints out the mac adresses for nearby devices, created by kalanda: esp8266-sniffer.
Aswell as this HTTP posting script ESP8266 http get requests.
I've tried to combine those two and in the callback function make the ESP send the found data, but doesn't look like the ESP establish the wifi connection.
I tried using different WIFI modes: STATION_MODE, SOFTAP_MODE, STATIONAP_MODE. None of them worked for both sniffing and http request at the same time. I know that the STATIONAP_MODE do have some flaws. What I've found is that it has to switch both somehow, but unfortunately I'm not a ESP expert and don't know how this can be done.
Here is my code(srry for any rubbish coding on my side):
#include <ESP8266WiFi.h> // added this
#include <ESP8266HTTPClient.h> // added this
const char* ssid = "**********"; // Wifi SSID
const char* password = "**********"; // Wifi Password
String main_url = "http://*********.php?"; // Website url to post the information
String temp_url = ""; // Url with information
extern "C" {
#include <user_interface.h>
}
#define DATA_LENGTH 112
#define TYPE_MANAGEMENT 0x00
#define TYPE_CONTROL 0x01
#define TYPE_DATA 0x02
#define SUBTYPE_PROBE_REQUEST 0x04
struct RxControl {
signed rssi:8; // signal intensity of packet
unsigned rate:4;
unsigned is_group:1;
unsigned:1;
unsigned sig_mode:2; // 0:is 11n packet; 1:is not 11n packet;
unsigned legacy_length:12; // if not 11n packet, shows length of packet.
unsigned damatch0:1;
unsigned damatch1:1;
unsigned bssidmatch0:1;
unsigned bssidmatch1:1;
unsigned MCS:7; // if is 11n packet, shows the modulation and code used (range from 0 to 76)
unsigned CWB:1; // if is 11n packet, shows if is HT40 packet or not
unsigned HT_length:16;// if is 11n packet, shows length of packet.
unsigned Smoothing:1;
unsigned Not_Sounding:1;
unsigned:1;
unsigned Aggregation:1;
unsigned STBC:2;
unsigned FEC_CODING:1; // if is 11n packet, shows if is LDPC packet or not.
unsigned SGI:1;
unsigned rxend_state:8;
unsigned ampdu_cnt:8;
unsigned channel:4; //which channel this packet in.
unsigned:12;
};
struct SnifferPacket{
struct RxControl rx_ctrl;
uint8_t data[DATA_LENGTH];
uint16_t cnt;
uint16_t len;
};
static void showMetadata(SnifferPacket *snifferPacket) {
unsigned int frameControl = ((unsigned int)snifferPacket->data[1] << 8) + snifferPacket->data[0];
uint8_t version = (frameControl & 0b0000000000000011) >> 0;
uint8_t frameType = (frameControl & 0b0000000000001100) >> 2;
uint8_t frameSubType = (frameControl & 0b0000000011110000) >> 4;
uint8_t toDS = (frameControl & 0b0000000100000000) >> 8;
uint8_t fromDS = (frameControl & 0b0000001000000000) >> 9;
// Only look for probe request packets
if (frameType != TYPE_MANAGEMENT ||
frameSubType != SUBTYPE_PROBE_REQUEST)
return;
Serial.print("RSSI: ");
Serial.print(snifferPacket->rx_ctrl.rssi, DEC);
Serial.print(" Ch: ");
Serial.print(wifi_get_channel());
char addr[] = "00:00:00:00:00:00";
getMAC(addr, snifferPacket->data, 10);
Serial.print(" Peer MAC: ");
Serial.print(addr);
uint8_t SSID_length = snifferPacket->data[25];
Serial.print(" SSID: ");
printDataSpan(26, SSID_length, snifferPacket->data);
Serial.println();
if (WiFi.status() == WL_CONNECTED) //Check WiFi connection status
{
HTTPClient http; //Declare an object of class HTTPClient
temp_url = main_url;
temp_url = temp_url + "mac=30:a8:db:96:a4:75";
temp_url = temp_url + "&rssi=-90";
temp_url = temp_url + "&ssid=none";
http.begin(temp_url); //Specify request destination
int httpCode = http.GET(); //Send the request
temp_url = "";
if (httpCode > 0)
{ //Check the returning code
String payload = http.getString(); //Get the request response payload
Serial.println(payload); //Print the response payload
}
http.end(); //Close connection
}
else
{
Serial.println("Wifi connection failed"); //Prints out this
}
}
/**
* Callback for promiscuous mode
*/
static void ICACHE_FLASH_ATTR sniffer_callback(uint8_t *buffer, uint16_t length) {
struct SnifferPacket *snifferPacket = (struct SnifferPacket*) buffer;
showMetadata(snifferPacket);
}
static void printDataSpan(uint16_t start, uint16_t size, uint8_t* data) {
for(uint16_t i = start; i < DATA_LENGTH && i < start+size; i++) {
Serial.write(data[i]);
}
}
static void getMAC(char *addr, uint8_t* data, uint16_t offset) {
sprintf(addr, "%02x:%02x:%02x:%02x:%02x:%02x", data[offset+0], data[offset+1], data[offset+2], data[offset+3], data[offset+4], data[offset+5]);
}
#define CHANNEL_HOP_INTERVAL_MS 1000
static os_timer_t channelHop_timer;
/**
* Callback for channel hoping
*/
void channelHop()
{
// hoping channels 1-14
uint8 new_channel = wifi_get_channel() + 1;
if (new_channel > 14)
new_channel = 1;
wifi_set_channel(new_channel);
}
#define DISABLE 0
#define ENABLE 1
void setup() {
// set the WiFi chip to "promiscuous" mode aka monitor mode
Serial.begin(115200);
delay(10);
wifi_set_opmode(STATION_MODE);
wifi_set_channel(1);
wifi_promiscuous_enable(DISABLE);
delay(10);
wifi_set_promiscuous_rx_cb(sniffer_callback);
delay(10);
wifi_promiscuous_enable(ENABLE);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print("Connecting..");
}
Serial.println("");
Serial.println("Connected..");
// setup the channel hoping callback timer
os_timer_disarm(&channelHop_timer);
os_timer_setfn(&channelHop_timer, (os_timer_func_t *) channelHop, NULL);
os_timer_arm(&channelHop_timer, CHANNEL_HOP_INTERVAL_MS, 1);
}
void loop() {
delay(10);
}
Here's the code which aggregates probe requests (MAC addresses and RSSIs) for 3 seconds and then sends them to specified server's endpoint using json (WIFI_AP_STA mode):
#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266HTTPClient.h>
#include <vector>
const char* apSsid = "ap-ssid";
const char* apPassword = "ap-password";
const char* clientSsid = "client-ssid";
const char* clientPassword = "client-password";
HTTPClient http;
WiFiEventHandler probeRequestPrintHandler;
String macToString(const unsigned char* mac) {
char buf[20];
snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
return String(buf);
}
std::vector<WiFiEventSoftAPModeProbeRequestReceived> myList;
void onProbeRequestPrint(const WiFiEventSoftAPModeProbeRequestReceived& evt) {
myList.push_back(evt);
}
void setup() {
Serial.begin(115200);
Serial.println("Hello!");
// Don't save WiFi configuration in flash - optional
WiFi.persistent(false);
WiFi.mode(WIFI_AP_STA);
WiFi.softAP(apSsid, apPassword);
WiFi.begin(clientSsid, clientPassword);
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(100);
}
Serial.println("");
probeRequestPrintHandler = WiFi.onSoftAPModeProbeRequestReceived(&onProbeRequestPrint);
}
void loop() {
delay(3000);
String json = "";
DynamicJsonBuffer jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
JsonArray& probes = root.createNestedArray("probes");
for(WiFiEventSoftAPModeProbeRequestReceived w : myList){
JsonObject& probe = probes.createNestedObject();
probe["address"] = macToString(w.mac);
probe["rssi"] = w.rssi;
}
myList.clear();
root.printTo(json);
Serial.println("json:" + json);
http.begin("http://example.com/api/v1/probe");
http.addHeader("Content-Type", "application/json");
http.POST(json);
http.end();
}
Remember to use the latest version (actually a pre-release - 2.4.0-rc1 or newer) of arduino-esp8266 library since those WiFiEvents were just recently added.
You can download ArduinoJson library using Library Manager (Sketch -> Include Library -> Manage Libraries...) if you don't have that already.

Unable to run input cature mode with SPI

I am Trying to run a web-server on AVR ATmega8 using ENC28J60 module. For this I got sample code from here. This code is working fine. Here is my code:-
#define F_CPU 8000000UL
#include <avr/io.h>
#include <string.h>
#include "ip_arp_udp_tcp.h"
#include "enc28j60.h"
#include "timeout.h"
#include "avr_compat.h"
#include "net.h"
// please modify the following two lines. mac and ip have to be unique
// in your local area network. You can not have the same numbers in
// two devices:
static uint8_t mymac[6] = {0x54,0x55,0x58,0x10,0x00,0x24};
// how did I get the mac addr? Translate the first 3 numbers into ascii is: TUX
static uint8_t myip[4] = {192,168,24,39};
// listen port for www
#define MYWWWPORT 80
//// listen port for udp
#define MYUDPPORT 1200
//
#define BUFFER_SIZE 450
static uint8_t buf[BUFFER_SIZE+1];
int main(void)
{
uint16_t plen;
uint16_t dat_p;
uint8_t i=0;
uint8_t payloadlen=0;
_delay_loop_1(50);
/*initialize enc28j60*/
enc28j60Init(mymac);
enc28j60clkout(2); // change clkout from 6.25MHz to 12.5MHz
_delay_loop_1(50); // 12ms
enc28j60PhyWrite(PHLCON,0x476);
_delay_loop_1(50); // 12ms
//init the ethernet/ip layer:
init_ip_arp_udp_tcp(mymac,myip,MYWWWPORT);
while(1)
{
// get the next new packet:
plen = enc28j60PacketReceive(BUFFER_SIZE, buf);
/*plen will ne unequal to zero if there is a valid * packet (without crc error) */
if(plen==0)
{
continue;
}
// arp is broadcast if unknown but a host may also
// verify the mac address by sending it to
// a unicast address.
if(eth_type_is_arp_and_my_ip(buf,plen))
{
make_arp_answer_from_request(buf);
continue;
}
// check if ip packets (icmp or udp) are for us:
if(eth_type_is_ip_and_my_ip(buf,plen)==0)
{
continue;
}
if(buf[IP_PROTO_P]==IP_PROTO_ICMP_V && buf[ICMP_TYPE_P]==ICMP_TYPE_ECHOREQUEST_V)
{
// a ping packet, let's send pong
make_echo_reply_from_request(buf,plen);
continue;
}
// tcp port www start, compare only the lower byte
if (buf[IP_PROTO_P]==IP_PROTO_TCP_V&&buf[TCP_DST_PORT_H_P]==0&&buf[TCP_DST_PORT_L_P]==MYWWWPORT)
{
if (buf[TCP_FLAGS_P] & TCP_FLAGS_SYN_V)
{
make_tcp_synack_from_syn(buf);
// make_tcp_synack_from_syn does already send the syn,ack
continue;
}
if (buf[TCP_FLAGS_P] & TCP_FLAGS_ACK_V)
{
init_len_info(buf); // init some data structures
// we can possibly have no data, just ack:
dat_p=get_tcp_data_pointer();
if (dat_p==0)
{
if (buf[TCP_FLAGS_P] & TCP_FLAGS_FIN_V)
{
// finack, answer with ack
make_tcp_ack_from_any(buf);
}
// just an ack with no data, wait for next packet
continue;
}
if (strncmp("GET ",(char *)&(buf[dat_p]),4)!=0)
{
plen=fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n<h1>200 OK</h1>"));
}
else
{
// Web Code
plen=fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n<p>PLANETCAST MEDIA SERVICES LTD</p>"));
plen=fill_tcp_data_p(buf,plen,PSTR("<body>"));
plen=fill_tcp_data_p(buf,plen,PSTR("<input type=\"text\" id=\"myurl\" name=\"url\" placeholder=\"Enter Url\"/><br>"));
plen=fill_tcp_data_p(buf,plen,PSTR("<input type=\"submit\" id=\"clickbutton\" name=\"Click Here\" />"));
plen=fill_tcp_data_p(buf,plen,PSTR("<script type=\"text/javascript\">"));
plen=fill_tcp_data_p(buf,plen,PSTR("document.getElementById(\"clickbutton\").onclick = function(){"));
plen=fill_tcp_data_p(buf,plen,PSTR("var url = document.getElementById(\"myurl\").value;"));
plen=fill_tcp_data_p(buf,plen,PSTR("location.href=url;"));
plen=fill_tcp_data_p(buf,plen,PSTR("};"));
plen=fill_tcp_data_p(buf,plen,PSTR("</script>"));
plen=fill_tcp_data_p(buf,plen,PSTR("</body"));
}
make_tcp_ack_from_any(buf); // send ack for http get
make_tcp_ack_with_data(buf,plen); // send data
continue;
}
}
// udp interface:
if (buf[IP_PROTO_P]==IP_PROTO_UDP_V)
{
payloadlen=buf[UDP_LEN_L_P]-UDP_HEADER_LEN;
// the received command has to start with t and be 4 char long
// e.g "test\0"
if (buf[UDP_DATA_P]=='t' && payloadlen==5)
{
make_udp_reply_from_request(buf,"hello",6,MYUDPPORT);
}
}
}
return (0);
}
Now I want to add Input Capture Mode , so I add interrupt header file then start Input capture mode in main() and then introduce sei() function. Now My code look like this:-
#define F_CPU 8000000UL
#include <avr/io.h>
#include <string.h>
#include "ip_arp_udp_tcp.h"
#include "enc28j60.h"
#include "timeout.h"
#include "avr_compat.h"
#include "net.h"
#include <avr/interrupt.h>
// please modify the following two lines. mac and ip have to be unique
// in your local area network. You can not have the same numbers in
// two devices:
static uint8_t mymac[6] = {0x54,0x55,0x58,0x10,0x00,0x24};
// how did I get the mac addr? Translate the first 3 numbers into ascii is: TUX
static uint8_t myip[4] = {192,168,24,39};
// listen port for www
#define MYWWWPORT 80
//// listen port for udp
#define MYUDPPORT 1200
//
#define BUFFER_SIZE 450
static uint8_t buf[BUFFER_SIZE+1];
int main(void)
{
TCCR1A = 0;
TCCR1B = (1<<ICNC1)|(1<<ICES1)|(1<<CS11);
TIMSK = (1<<TICIE1);
TCNT1 = 0;
sei();
uint16_t plen;
uint16_t dat_p;
uint8_t i=0;
uint8_t payloadlen=0;
_delay_loop_1(50);
/*initialize enc28j60*/
enc28j60Init(mymac);
enc28j60clkout(2); // change clkout from 6.25MHz to 12.5MHz
_delay_loop_1(50); // 12ms
enc28j60PhyWrite(PHLCON,0x476);
_delay_loop_1(50); // 12ms
//init the ethernet/ip layer:
init_ip_arp_udp_tcp(mymac,myip,MYWWWPORT);
while(1)
{
// get the next new packet:
plen = enc28j60PacketReceive(BUFFER_SIZE, buf);
/*plen will ne unequal to zero if there is a valid * packet (without crc error) */
if(plen==0)
{
continue;
}
// arp is broadcast if unknown but a host may also
// verify the mac address by sending it to
// a unicast address.
if(eth_type_is_arp_and_my_ip(buf,plen))
{
make_arp_answer_from_request(buf);
continue;
}
// check if ip packets (icmp or udp) are for us:
if(eth_type_is_ip_and_my_ip(buf,plen)==0)
{
continue;
}
if(buf[IP_PROTO_P]==IP_PROTO_ICMP_V && buf[ICMP_TYPE_P]==ICMP_TYPE_ECHOREQUEST_V)
{
// a ping packet, let's send pong
make_echo_reply_from_request(buf,plen);
continue;
}
// tcp port www start, compare only the lower byte
if (buf[IP_PROTO_P]==IP_PROTO_TCP_V&&buf[TCP_DST_PORT_H_P]==0&&buf[TCP_DST_PORT_L_P]==MYWWWPORT)
{
if (buf[TCP_FLAGS_P] & TCP_FLAGS_SYN_V)
{
make_tcp_synack_from_syn(buf);
// make_tcp_synack_from_syn does already send the syn,ack
continue;
}
if (buf[TCP_FLAGS_P] & TCP_FLAGS_ACK_V)
{
init_len_info(buf); // init some data structures
// we can possibly have no data, just ack:
dat_p=get_tcp_data_pointer();
if (dat_p==0)
{
if (buf[TCP_FLAGS_P] & TCP_FLAGS_FIN_V)
{
// finack, answer with ack
make_tcp_ack_from_any(buf);
}
// just an ack with no data, wait for next packet
continue;
}
if (strncmp("GET ",(char *)&(buf[dat_p]),4)!=0)
{
plen=fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n<h1>200 OK</h1>"));
}
else
{
// Web Code
plen=fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n<p>PLANETCAST MEDIA SERVICES LTD</p>"));
plen=fill_tcp_data_p(buf,plen,PSTR("<body>"));
plen=fill_tcp_data_p(buf,plen,PSTR("<input type=\"text\" id=\"myurl\" name=\"url\" placeholder=\"Enter Url\"/><br>"));
plen=fill_tcp_data_p(buf,plen,PSTR("<input type=\"submit\" id=\"clickbutton\" name=\"Click Here\" />"));
plen=fill_tcp_data_p(buf,plen,PSTR("<script type=\"text/javascript\">"));
plen=fill_tcp_data_p(buf,plen,PSTR("document.getElementById(\"clickbutton\").onclick = function(){"));
plen=fill_tcp_data_p(buf,plen,PSTR("var url = document.getElementById(\"myurl\").value;"));
plen=fill_tcp_data_p(buf,plen,PSTR("location.href=url;"));
plen=fill_tcp_data_p(buf,plen,PSTR("};"));
plen=fill_tcp_data_p(buf,plen,PSTR("</script>"));
plen=fill_tcp_data_p(buf,plen,PSTR("</body"));
}
make_tcp_ack_from_any(buf); // send ack for http get
make_tcp_ack_with_data(buf,plen); // send data
continue;
}
}
// udp interface:
if (buf[IP_PROTO_P]==IP_PROTO_UDP_V)
{
payloadlen=buf[UDP_LEN_L_P]-UDP_HEADER_LEN;
// the received command has to start with t and be 4 char long
// e.g "test\0"
if (buf[UDP_DATA_P]=='t' && payloadlen==5)
{
make_udp_reply_from_request(buf,"hello",6,MYUDPPORT);
}
}
}
return (0);
}
ISR(TIMER1_CAPT_vect)
{
//do something
}
Now when I run my code , I got no webpage on my browser. So, I comment out sei() function. After this my code works fine. So, I check SPI settings in enc28j60.c. As per my knowledge SPI is not running on interrupt , so it shouldn't be affected by sei(). Here is my SPi settings in enc28j60.c:-
#define ENC28J60_CONTROL_PORT PORTB
#define ENC28J60_CONTROL_DDR DDRB
#define ENC28J60_CONTROL_CS 2
#define ENC28J60_CONTROL_SO 4
#define ENC28J60_CONTROL_SI 3
#define ENC28J60_CONTROL_SCK 5
void enc28j60Init(uint8_t* macaddr)
{
// initialize I/O
// ss as output:
ENC28J60_CONTROL_DDR |= 1<<ENC28J60_CONTROL_CS;
CSPASSIVE; // ss=0
//
ENC28J60_CONTROL_DDR |= 1<<ENC28J60_CONTROL_SI | 1<<ENC28J60_CONTROL_SCK; // mosi, sck output
cbi(ENC28J60_CONTROL_DDR,ENC28J60_CONTROL_SO); // MISO is input
//
cbi(ENC28J60_CONTROL_PORT,ENC28J60_CONTROL_SI); // MOSI low
cbi(ENC28J60_CONTROL_PORT,ENC28J60_CONTROL_SCK); // SCK low
So, can anyone tell me why my SPI mode is geting effected by sei() function and how get rid of this.
I have not read all your code but i think you are all time in interrupt. In normal mode the timer are not reset when it reach the top. Try with TCNT1 = 0; in the ISR.

Why does UART transmit interrupt fail to work in this case?

I am using stm32f0 MCU.
I have a simple UART echo code in which every byte received will be transmitted out. I tested that it works. Here it is;
uint8_t Rx_data[5];
uint32_t tx_timeout = 0;
//Interrupt callback routine
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1) //current UART
{
HAL_UART_Transmit(&huart1, &Rx_data[0], 1, tx_timeout);
HAL_UART_Receive_IT(&huart1, Rx_data, 1); //activate UART receive interrupt every time on receiving 1 byte
}
}
I do not feel comfortable with the code even though it works. Firstly, tx_timeout is 0 and most code examples are non-zero. I do not know the side effect. Secondly, HAL_UART_Transmit() is a blocking call and it is not advisable to use blocking calls inside an interrupt. So, I decided to use an interrupt for uart transmission HAL_UART_Transmit_IT()instead of a blocking call. Here is the modified code;
uint8_t Rx_data[5];
uint32_t tx_timeout = 0;
//Interrupt callback routine
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1) //current UART
{
HAL_UART_Transmit_IT(&huart1, &Rx_data[0], 1);
HAL_UART_Receive_IT(&huart1, Rx_data, 1); //activate UART receive interrupt every time on receiving 1 byte
}
}
However, it does not work as expected. My PC transmits ASCII 12345678 to stm32. If things work as expected, the PC should be receiving 12345678 back. However, the PC receives 1357 instead. What is wrong with this code that uses HAL_UART_Transmit_IT()?
First:
As has been described in answers to your previous question null timeout just exclude wait for flag state. If you open HAL_UART_Transmit code - you will see that when you send 1 byte without timeout no any blocking state will!
Second:
It's not true method to send/receive one byte from a huge HAL's functions and their callbacks. I guess: next your question will "how i must implement parse there?". And I hope you will not insert you parse function in IRQ callback!
So generally you need buffers. And it is good idea to use cyclic buffer.
mxconstants.h:
/* USER CODE BEGIN Private defines */
/* Buffer's length must be select according to real messages frequency */
#define RXBUF_LEN 128 // must be power of 2
#define TXBUF_LEN 128 // must be power of 2
#define RXBUF_MSK (RXBUF_LEN-1)
#define TXBUF_MSK (TXBUF_LEN-1)
/* USER CODE END Private defines */
main.c:
uint8_t rx_buf[RXBUF_LEN], tx_buf[TXBUF_LEN];
/* xx_i - counter of input bytes (tx - pushed for transmit, rx - received)
xx_o - counter of output bytes (tx - transmitted, rx - parsed)
xx_e - counter of echoed bytes */
volatile uint16_t rx_i = 0, tx_o = 0;
uint16_t rx_o = 0, rx_e = 0, tx_i = 0;
volatile uint8_t tx_busy = 0;
void transmit(uint8_t byte)
{
tx_buf[TXBUF_MSK & tx_i] = byte;
tx_i++;
tx_busy = 1;
__HAL_UART_ENABLE_IT(&huart1, UART_IT_TXE);
}
void main(void)
{
/* Initialization code */
/* ... */
/* Enable usart 1 receive IRQ */
__HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE);
for (;;) {
/* Main cycle */
while (rx_i != rx_e) {
/* echo here */
transmit(rx_buf[RXBUF_MSK & rx_e]);
rx_e++;
}
while (rx_i != rx_o) {
/* parse here */
/* ... */
rx_o++;
}
/* Power save
while (tx_busy);
HAL_UART_DeInit(&huart1);
*/
}
}
stm32f0xx_it.c:
extern uint8_t rx_buf[RXBUF_LEN], tx_buf[TXBUF_LEN];
extern volatile uint16_t rx_i, tx_o;
extern uint16_t rx_o, rx_e, tx_i;
extern volatile uint8_t tx_busy;
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
if((__HAL_UART_GET_IT(&huart1, UART_IT_RXNE) != RESET) &&
(__HAL_UART_GET_IT_SOURCE(&huart1, UART_IT_RXNE) != RESET))
{
rx_buf[rx_i & RXBUF_MSK] = (uint8_t)(huart1.Instance->RDR & 0x00FF);
rx_i++;
/* Clear RXNE interrupt flag */
__HAL_UART_SEND_REQ(&huart1, UART_RXDATA_FLUSH_REQUEST);
}
if((__HAL_UART_GET_IT(&huart1, UART_IT_TXE) != RESET) &&
(__HAL_UART_GET_IT_SOURCE(&huart1, UART_IT_TXE) != RESET))
{
if (tx_i == tx_o) {
__HAL_UART_DISABLE_IT(&huart1, UART_IT_TXE);
__HAL_UART_ENABLE_IT(&huart1, UART_IT_TC);
} else {
huart1.Instance->TDR = (uint8_t)(tx_buf[TXBUF_MSK & tx_o] & (uint8_t)0xFF);
tx_o++;
}
}
if((__HAL_UART_GET_IT(&huart1, UART_IT_TC) != RESET) &&
(__HAL_UART_GET_IT_SOURCE(&huart1, UART_IT_TC) != RESET))
{
tx_busy = 0;
__HAL_UART_DISABLE_IT(&huart1, UART_IT_TC);
}
/* And never call default handler */
return;
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
}
And third!!!
And about this:
Why HAL_UART_Transmit_IT not help/work?
Because it's too slow! And if you try to count HAL_BUSY results:
uint8_t Rx_data[5];
uint32_t tx_timeout = 0;
//Interrupt callback routine
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
static uint32_t hal_busy_counter = 0;
if (huart->Instance == USART1) //current UART
{
if (HAL_UART_Transmit_IT(&huart1, &Rx_data[0], 1) == HAL_BUSY) {
hal_busy_counter++;
}
HAL_UART_Receive_IT(&huart1, Rx_data, 1); //activate UART receive interrupt every time on receiving 1 byte
}
}
When you pause MCU in debugger after data exchange - you will be suprised: it will be equal to count of missed chars.

Creating a RAW UDP connection in lwip ARP

I am currently working to create a simple transfer protocol over Ethernet. I have a SP605 Xilinx evaluation board which I am using to debug the Ethernet portion of our project. I attempted to cannibalize the example but have so far been unsuccessful. Currently, the communication needs to only be one way. Currently, I am trying to see the data being sent with netcat. I also have wireshark open and am seeing the system get stuck repeatedly asking:
2217 1323.697811000 Xilinx_00:01:02 Broadcast
ARP 60 Who has 192.168.1.11? Tell 192.168.1.10
I can see the Host computer reply with:
2217 1323.697811000 Xilinx_00:01:02 Broadcast
ARP 60 Who has 192.168.1.11? Tell 192.168.1.10
I feel like I have some issues with the configuration but cannot figure out how what it is. I think it might have something to do with a not having a recv handler set but I am not sure.
Below is the code I am using. lwip_init() is mimicking the call from the examples provided by Xilinx.
/*
* main.c
*
* Created on: Sep 24, 2013
* Author: Ian
*/
#include <stdio.h>
#include <string.h>
#include <stdio.h>
#include "lwip/init.h"
#include "xparameters.h"
#include "netif/xadapter.h"
#include "xenv_standalone.h"
#include "platform_config.h"
#include "xparameters.h"
#include "xintc.h"
#include "xil_exception.h"
#include "mb_interface.h"
#include "xtmrctr_l.h"
#include "lwip/udp.h"
#include "lwipopts.h"
#include "xil_printf.h"
struct ip_addr ipaddr, ipaddr_remote, netmask, gw;
void udp_test(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port);
void print_ip(char *msg, struct ip_addr *ip)
{
print(msg);
xil_printf("%d.%d.%d.%d\r\n", ip4_addr1(ip), ip4_addr2(ip),
ip4_addr3(ip), ip4_addr4(ip));
}
void print_ip_settings(struct ip_addr *ip, struct ip_addr *mask, struct ip_addr *gw)
{
print_ip("Board IP: ", ip);
print_ip("Netmask : ", mask);
print_ip("Gateway : ", gw);
}
int main()
{
err_t error;
struct netif *netif, server_netif;
struct udp_pcb *udp_1;
struct pbuf *p;
char data[8] = "01234567";
u16_t Port;
Port = 69;
int count = 0;
int n = 0;
int buflen = 8;
/* the mac address of the board. this should be unique per board */
unsigned char mac_ethernet_address[] = { 0x00, 0x0a, 0x35, 0x00, 0x01, 0x02 };
netif = &server_netif;
xil_printf("\r\n\r\n");
xil_printf("-----lwIP RAW Application ------\r\n");
/* initliaze IP addresses to be used */
IP4_ADDR(&ipaddr_remote, 192, 168, 1, 11);
IP4_ADDR(&ipaddr, 192, 168, 1, 10);
IP4_ADDR(&netmask, 255, 255, 255, 0);
IP4_ADDR(&gw, 192, 168, 1, 1);
print_ip_settings(&ipaddr, &netmask, &gw);
lwip_init();
if (!xemac_add(netif, &ipaddr, &netmask, &gw, mac_ethernet_address, PLATFORM_EMAC_BASEADDR)) {
xil_printf("Error adding N/W interface\r\n");
return -1;
}
netif_set_default(netif);
netif_set_up(netif);
Xil_ExceptionEnable(); //Setup complete start interrupts
udp_1 = udp_new();
error = udp_bind(udp_1, IP_ADDR_ANY, Port);
if (error != 0)
{
xil_printf("Failed %d\r\n", error);
}
else if (error == 0)
{
xil_printf("Success\r\n");
}
error = udp_connect(udp_1, &ipaddr_remote, Port);
if (error != 0)
{
xil_printf("Failed %d\r\n", error);
}
else if (error == 0)
{
xil_printf("Success\r\n");
}
while(1)
{
count++;
xemacif_input(netif);
if (count == 100000)
{
p = pbuf_alloc(PBUF_TRANSPORT, buflen, PBUF_POOL);
if (!p) {
xil_printf("error allocating pbuf\r\n");
return ERR_MEM;
}
memcpy(p->payload, data, buflen);
udp_send(udp_1, p);
xil_printf("SEND\r\n");
count = 0;
pbuf_free(p);
}
}
data[1] = '2';
}
Ok, so basically here is what I found.
The Xilinx xapp1026 had issues with the sp605_AxiEth_32kb_Cache project when I used it. It was hanging at the start interrupts. I was not able to diagnose the project BUT I switched to the sp605_EthernetLite_32kb_Cache example project. I can only assume that the failure of the MicroBlaze interrupts to initialize caused the ARP to fail to get added and forced the system into the loop repeatedly. It is still unclear why the interrupt failed to initialize in the AxiEth example.
Once here I was able to get a program to work by stripping down the provided system and using the following code:
/*
* Copyright (c) 2007 Xilinx, Inc. All rights reserved.
*
* Xilinx, Inc.
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
* COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
* ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
* STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
* IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
* FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
* XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
* THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
* ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
* FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE.
*
*/
#include <stdio.h>
#include <string.h>
#include "lwip/udp.h"
#include "xparameters.h"
#include "netif/xadapter.h"
#include "platform.h"
#include "platform_config.h"
#include "lwipopts.h"
#ifndef __PPC__
#include "xil_printf.h"
#endif
void print_headers();
int start_applications();
int transfer_data();
void platform_enable_interrupts();
void lwip_init(void);
void tcp_fasttmr(void);
void tcp_slowtmr(void);
#if LWIP_DHCP==1
extern volatile int dhcp_timoutcntr;
err_t dhcp_start(struct netif *netif);
#endif
extern volatile int TxPerfConnMonCntr;
extern volatile int TcpFastTmrFlag;
extern volatile int TcpSlowTmrFlag;
void print_ip(char *msg, struct ip_addr *ip)
{
print(msg);
xil_printf("%d.%d.%d.%d\r\n", ip4_addr1(ip), ip4_addr2(ip),
ip4_addr3(ip), ip4_addr4(ip));
}
void print_ip_settings(struct ip_addr *ip, struct ip_addr *mask, struct ip_addr *gw)
{
print_ip("Board IP: ", ip);
print_ip("Netmask : ", mask);
print_ip("Gateway : ", gw);
}
int main()
{
struct netif *netif, server_netif;
struct ip_addr ipaddr, netmask, gw;
// Added stuff for the creation of a basic UDP
err_t error;
struct ip_addr ip_remote;
struct udp_pcb *udp_1;
struct pbuf *p;
char data[8] = "01234567";
u16_t Port = 12;
int buflen = 8;
int count = 0;
/* the mac address of the board. this should be unique per board */
unsigned char mac_ethernet_address[] = { 0x00, 0x0a, 0x35, 0x00, 0x01, 0x02 };
netif = &server_netif;
if (init_platform() < 0) {
xil_printf("ERROR initializing platform.\r\n");
return -1;
}
xil_printf("\r\n\r\n");
xil_printf("-----lwIP RAW Mode Demo Application ------\r\n");
/* initliaze IP addresses to be used */
#if (LWIP_DHCP==0)
IP4_ADDR(&ipaddr, 192, 168, 1, 10);
IP4_ADDR(&netmask, 255, 255, 255, 0);
IP4_ADDR(&gw, 192, 168, 1, 1);
print_ip_settings(&ipaddr, &netmask, &gw);
#endif
lwip_init();
#if (LWIP_DHCP==1)
ipaddr.addr = 0;
gw.addr = 0;
netmask.addr = 0;
#endif
/* Add network interface to the netif_list, and set it as default */
if (!xemac_add(netif, &ipaddr, &netmask, &gw, mac_ethernet_address, PLATFORM_EMAC_BASEADDR)) {
xil_printf("Error adding N/W interface\r\n");
return -1;
}
netif_set_default(netif);
/* specify that the network if is up */
netif_set_up(netif);
/* now enable interrupts */
platform_enable_interrupts();
#if (LWIP_DHCP==1)
/* Create a new DHCP client for this interface.
* Note: you must call dhcp_fine_tmr() and dhcp_coarse_tmr() at
* the predefined regular intervals after starting the client.
*/
dhcp_start(netif);
dhcp_timoutcntr = 24;
TxPerfConnMonCntr = 0;
while(((netif->ip_addr.addr) == 0) && (dhcp_timoutcntr > 0)) {
xemacif_input(netif);
if (TcpFastTmrFlag) {
tcp_fasttmr();
TcpFastTmrFlag = 0;
}
if (TcpSlowTmrFlag) {
tcp_slowtmr();
TcpSlowTmrFlag = 0;
}
}
if (dhcp_timoutcntr <= 0) {
if ((netif->ip_addr.addr) == 0) {
xil_printf("DHCP Timeout\r\n");
xil_printf("Configuring default IP of 192.168.1.10\r\n");
IP4_ADDR(&(netif->ip_addr), 192, 168, 1, 10);
IP4_ADDR(&(netif->netmask), 255, 255, 255, 0);
IP4_ADDR(&(netif->gw), 192, 168, 1, 1);
}
}
/* receive and process packets */
print_ip_settings(&(netif->ip_addr), &(netif->netmask), &(netif->gw));
#endif
/* start the application (web server, rxtest, txtest, etc..) */
xil_printf("Setup Done");
IP4_ADDR(&ip_remote, 192, 168, 1, 11);
udp_1 = udp_new();
error = udp_bind(udp_1, IP_ADDR_ANY, Port);
if (error != 0)
{
xil_printf("Failed %d\r\n", error);
}
else if (error == 0)
{
xil_printf("Success\r\n");
}
error = udp_connect(udp_1, &ip_remote, Port);
if (error != 0)
{
xil_printf("Failed %d\r\n", error);
}
else if (error == 0)
{
xil_printf("Success\r\n");
}
while (1)
{
xemacif_input(netif);
count++;
if (count == 80000)
{
p = pbuf_alloc(PBUF_TRANSPORT, buflen, PBUF_POOL);
if (!p) {
xil_printf("error allocating pbuf\r\n");
return ERR_MEM;
}
memcpy(p->payload, data, buflen);
udp_send(udp_1, p);
xil_printf("SEND\r\n");
count = 0;
pbuf_free(p);
}
}
/* never reached */
cleanup_platform();
return 0;
}
----Edit ----
So you know how people figure it out then don't leave an answer. Well here was my problem with the orginal code (I think..) the line of code xemacif_input(netif); gives the Ethernet the ability to process the arp call without it the FPGA will sending out the ARP and then not receiving it will ask repeatedly.
The previous code does appear to have the correct line of code in it. So it might have been a mistake in how the interrupts were configured.
I got this example working and implemented it in my project. If you have questions about this please ask and I will try and give the best answers I can.