I have a problem , please help me.
for about a project homework ı need read from virtual serial port with microC and send this info to AT89C52 microconttoller..
This is my source code:
int uart_rd;
void main() {
P1=0X00;
UART1_Init(9600);
delay_ms(100);
while(1)
{
if(UART1_Data_Ready()){
uart_rd=UART1_read();
if(uart_rd=='1')
{P1=0X01; delay_ms(1500); P1=0X00; }
if(uart_rd=='2')
{P1=0X02; delay_ms(1500); P1=0X00; }
}
}
}
BUT I cant get info from the port. Where is the mistake.Please help me...
You are defining your UART receive variable (uart_rd) as an int, which is a 2 byte variable. I would expect UART1_read() to return a single byte (char).
I am not familiar with your particular setup or debugging/troubleshooting options, but you might try writing some code to assist in debugging your issue. The following example may be useful. It does assume that LEDs are connected to both port 1 and port 2, so some adjustment may be necessary.
char uart_rd;
void main()
{
UART1_Init(9600); // Initialize UART at 9600 bps
delay_ms(100); // Wait for UART to stabilize
while(1)
{
if(UART1_Data_Ready())
{
P2 = 0xFF; // Turn ON PORT2 LEDs upon data ready
uart_rd = UART1_read(); // Receive data
P1 = uart_rd; // Display data on port 1 LEDs
UART1_write(uart_rd); // Transmit same data back
delay_ms(1500); // Brief delay
P1 = 0x00; // Turn OFF port 1 LEDs
P2 = 0x00; // Turn OFF port 2 LEDs
}
}
}
Related
I am trying a lot of days to acomplish a communication via spi (stm32-nrf24..) and it doesn't work despite that I had read a lot of resources I cant make it right and I dont know why this is happening, I realy need help. I have nucleol053r8 and nrf24l01 and I want to accive a communication between them. When I am truing to debug the spi, for example to write something on DR and after to read it, nothing works! It seems that nothing is writing to DR.
My configurations for this communication are
CPOL=CPHA=0
FULL DUPLEX MODE
MSB FIRST
MASTER MODE ON
8bit DATA FRAME
SSM=SSI=1
Here is my functions for reading and writing.
void spi1_transmit(uint8_t *data,uint32_t size){
uint32_t i=0;
uint8_t temp;
while (i<size){
while (!READ_BIT(SPI1->SR,SPI_SR_TXE));
SPI1->DR=data[i];
i++;
}
while (!READ_BIT(SPI1->SR,SPI_SR_TXE));
while (READ_BIT(SPI1->SR,SPI_SR_BSY));
temp = SPI1->DR;
temp = SPI1->SR;
}
void spi1_receive(uint8_t *data,uint32_t size){
while (size){
SPI1->DR=0;
while (!READ_BIT(SPI1->SR,SPI_SR_RXNE));
*data++=(SPI1->DR);
size--;
}
}
void spi1_gpio_init(){
/*Enable clock access to GPIOA*/
SET_BIT(RCC->IOPENR,IOPAEN);
/*Setting as AF functions the proper pins. */
CLEAR_BIT(GPIOA->MODER,(1U<<10)); // PA5
SET_BIT(GPIOA->MODER,(1U<<11));
CLEAR_BIT(GPIOA->OTYPER,(1U<<5));
SET_BIT(GPIOA->OSPEEDR,(1U<<10));
SET_BIT(GPIOA->OSPEEDR,(1U<<11));
// Setting AF type AF0.
CLEAR_BIT(GPIOA->AFR[0],(1U<<20));
CLEAR_BIT(GPIOA->AFR[0],(1U<<21));
CLEAR_BIT(GPIOA->AFR[0],(1U<<22));
CLEAR_BIT(GPIOA->AFR[0],(1U<<23));
CLEAR_BIT(GPIOA->MODER,(1U<<12)); //PA6
SET_BIT(GPIOA->MODER,(1U<<13));
CLEAR_BIT(GPIOA->OTYPER,(1U<<6));
SET_BIT(GPIOA->OSPEEDR,(1U<<12));
SET_BIT(GPIOA->OSPEEDR,(1U<<13));
// Setting AF type AF0.
CLEAR_BIT(GPIOA->AFR[0],(1U<<24));
CLEAR_BIT(GPIOA->AFR[0],(1U<<25));
CLEAR_BIT(GPIOA->AFR[0],(1U<<26));
CLEAR_BIT(GPIOA->AFR[0],(1U<<27));
CLEAR_BIT(GPIOA->MODER,(1U<<14)); //PA7
SET_BIT(GPIOA->MODER,(1U<<15));
CLEAR_BIT(GPIOA->OTYPER,(1U<<7));
SET_BIT(GPIOA->OSPEEDR,(1U<<14));
SET_BIT(GPIOA->OSPEEDR,(1U<<15));
// Setting AF type AF0.
CLEAR_BIT(GPIOA->AFR[0],(1U<<28));
CLEAR_BIT(GPIOA->AFR[0],(1U<<29));
CLEAR_BIT(GPIOA->AFR[0],(1U<<30));
CLEAR_BIT(GPIOA->AFR[0],(1U<<31));
SET_BIT(GPIOA->MODER,(1U<<18)); //PA9
CLEAR_BIT(GPIOA->MODER,(1U<<19));
CLEAR_BIT(GPIOA->OTYPER,(1U<<9));
SET_BIT(GPIOA->OSPEEDR,(1U<<18));
SET_BIT(GPIOA->OSPEEDR,(1U<<19));
SET_BIT(GPIOA->MODER,(1U<<16)); //PA8
CLEAR_BIT(GPIOA->MODER,(1U<<17));
CLEAR_BIT(GPIOA->OTYPER,(1U<<8));
SET_BIT(GPIOA->OSPEEDR,(1U<<16));
SET_BIT(GPIOA->OSPEEDR,(1U<<17));
}
void spi1_config(){
/*Enable clock access to SPI1.*/
SET_BIT(RCC->APB2ENR,SPI1_EN);
/*Setting up BAUDRATE. FPCLK/32 (100) */
SET_BIT(SPI1->CR1,(1U<<5)); // 1.
CLEAR_BIT(SPI1->CR1,(1U<<4)); // 0.
CLEAR_BIT(SPI1->CR1,(1U<<3)); // 0.
/*Setting up CPOL=0 and CPHA=0.*/
CLEAR_BIT(SPI1->CR1,(1U<<0)); // CPHA=0.
CLEAR_BIT(SPI1->CR1,(1U<<1)); // CPOL=0.
/*Enable full-duplex mode.*/
CLEAR_BIT(SPI1->CR1,(1U<<10));
/*Set MSB first.*/
CLEAR_BIT(SPI1->CR1,(1U<<7));
/*Enable Master mode.*/
SET_BIT(SPI1->CR1,(1U<<2));
/*Setting up 8-bit data frame.*/
CLEAR_BIT(SPI1->CR1,(1U<<11));
/*Enable software slave management. SSM=1 and SSI=1.*/
SET_BIT(SPI1->CR1,(1U<<9)); // SSM=1.
SET_BIT(SPI1->CR1,(1U<<8)); // SSI=1.
cs_disable();
ce_disable();
/*Enable SPI peripheral.*/
SET_BIT(SPI1->CR1,(1U<<6));
}
and with this why am testing it
int main(void){
uint8_t tx_b[3],rx_b[3];
init_rcc();
spi1_gpio_init();
spi1_config();
tx_b[0]=0b00111111;
tx_b[1]=0b00001000;
tx_b[2]=0b00101000;
spi1_transmit(tx_b,3);
while(1){
spi1_receive(rx_b,3);
}
}
You need to enable SPI clock
You need to enable the peripheral
Many STM32 SPIs have FIFO and you need to force the compiler to generate the correct size store instructions.
For example
*(volatile uint8_t *)&SPI1->DR = data[i];
Currently, I have two, 2-Channel 1 Amp SPDT Signal Relay Controllers connected to my Raspberry Pi 3 via I2C, and when I currently run the function to turn one relay on, the other one will shut off at the same time (one or the other is on). In addition, my button to shut off relay 1 and my button to shut off relay 2 will shut both relays off.
My program is written in a windows form (visual studio), and I am accessing a C Shared Library via Dll Import, but I know for a fact my problem is within my C library. I am very new to C and how shifting works, so the root of my problem lies within the logic and structure of my code. Frankly, I'm confused on how to properly code this.
This is currently the method to turn Relay 1 On. It turns the relay on properly, but this also turns Relay 2 Off at the same time.
void Relay1On() ***CURRENTLY TURNS OTHER OFF WHEN ACTIVATED***
{
// Create I2C bus
int file;
char *bus = "/dev/i2c-1";
if ((file = open(bus, O_RDWR)) < 0)
{
printf("Failed to open the bus. \n");
exit(1);
}
// Get I2C device, MCP23008 I2C address is 0x20(32)
ioctl(file, I2C_SLAVE, 0x20);
// Configure all pins of port as output (0x00)
char config[2] = {0};
config[0] = 0x00;
config[1] = 0x00;
write(file, config, 2);
//Turn the first relay on
char data = 0x01;
config[0] = 0x09;
config[1] = data;
write(file, config, 2);
}
Here is the code for Relay 1 Off, I will not post Relay 2 On/Off because it is basically the same, Relay2On just has an added data += 1; after char data = 0x01;. Both 'Off' methods result in both relays shutting off.
void Relay1Off()
{
// Create I2C bus
int file;
char *bus = "/dev/i2c-1";
if ((file = open(bus, O_RDWR)) < 0)
{
printf("Failed to open the bus. \n");
exit(1);
}
// Get I2C device, MCP23008 I2C address is 0x20(32)
ioctl(file, I2C_SLAVE, 0x20);
// Configure all pins of port as output (0x00)
char config[2] = {0};
config[0] = 0x00;
config[1] = 0x00;
write(file, config, 2);
//Turn the first relay off *****Turns all off at the moment******
char data = 0xFE;
data = (data << 1);
config[0] = 0x09;
config[1] = data;
write(file, config, 2);
}
All I want is the methods to do as described, turn Relay 1 On when the method is called. When Relay1Off is called, shut only Relay 1 off. I'm sure it is simple, but as I've stated above C is quite new to me.
Thank you in advance for any contribution.
I don't know how the fancy ioctl stuff works, but I'd try to do all initialization outside of this function, including setting all the GPIO's to output.
You should probably just have one function call to set/clear a relay. I'd do something like this to start:
void RelayOnOff(unsigned char relay, unsigned char enable)
{
//Init to all off
static unsigned char data = 0x00;
...
if (enable){
data |= ( 1 << relay );
}
else{
data &= ~( 1 << relay );
}
config[0] = 0x09;
config[1] = data;
write(file, config, 2);
}
You pass in what relay you want to control, and a boolean value for enable/disable. If you make the data variable static, it'll "remember" that value from function call to function call. The enable/disable sets/clears the bit for whatever relay you pass in (0-7).
I am trying to receive multiple bytes over SPI. The aim is when the master starts the SPI transfer, slave MCU is interrupted, and it should read the data via SPI and store it in an array, which will be then used by my application for other operations such as determining the device ID and the contents of the packet.
void interrupt __high_priority my_isr_high(void) {
if (PIR1bits.SSP1IF) { // Interrupt from SPI?
rx[buffer_pointer] = SSP1BUF; // Get data from MSSP and store in RX buffer
buffer_pointer++; // Next data
if (buffer_pointer < FRAME_SIZE) // Ended?
SSP1BUF = tx[buffer_pointer]; // Send next byte to SPI
else
buffer_pointer = FRAME_SIZE;
PIR1bits.SSP1IF = 0; // Clear interrupt flag
}
}
However, I am not receiving the 3 bytes correctly. I am sending the following from the master:
dataPacket[0] = 0x43; // Decimal 67
dataPacket[1] = 0x42; //66
dataPacket[2] = 0x41; //65
While I am receiving as follows from the ISR():
rx[0]: 67
rx[1]: 65
rx[2]: 67
Am I missing something or handling the SPI incorrectly?
This will really solve the issue that I am stuck with and maybe will also help others who what to rx multiple bytes.
I am sharing my codes here so that it helps to find the solution quickly. Also included is a .zip file for compiling. Check the Codes here
So far the above code did not work for me properly. Therefore, after a little bit of digging online and other forums I found the following way to read multiple bytes:
uint8_t SPI_ExchangeHandler(uint8_t byte){
static uint8_t i = 0;
for(i=0; i<3; i++){
SSP1BUF =0x00;
while(!SSP1STATbits.BF);
rx_buff[i]=SSP1BUF;
}
State = SEND;
return byte;
}
Although the above codes give me what expected (i.e, correct data packets in the ordered manner), however, it misses two SPI interrupts every time and then displays/captures the correct data. Hence, two sets of data are always lost and then the third one is received correctly.
Is something wrongly configured or missing?
Finally, I managed to receive all the 3 bytes correctly. Sharing the codes below:
My interrupt service routine that triggers the MCU when master SPI has data to send.
void interrupt INTERRUPT_InterruptManager (void){
if(PIE1bits.SSP1IE == 1 && PIR1bits.SSP1IF == 1)
{
SPI_ISR();
}
}
The SPI_ISR code was autogenerated by the MCC GUI.
void SPI_ISR(void)
{
SSP1BUF = SPI_xchgHandler(SSP1BUF);
}
void SPI_setExchangeHandler(uint8_t (* InterruptHandler)(uint8_t))
{
SPI_xchgHandler = InterruptHandler;
}
Then I handle the SPI via a custom function using SPI_setExchangeHandler() as follows:
#define FRAME_SIZE 10 // Frame fixed size
volatile static uint8_t rx_buff[FRAME_SIZE]; //RX buffer
uint8_t SPI_ExchangeHandler(uint8_t byte)
{
static uint8_t i = 0;
rx_buff[i]=SSP1BUF;
i++;
if(i <= 2){
rx_buff[i]=SSP1BUF;
SSP1BUF = 0x00;
while(!SSP1STATbits.BF){};
i++;
}
else{
i = 2;
}
PIR1bits.SSP1IF = 0; // Clear the SPI interrupt flag
State = SEND;
return byte;
}
And I print out the values as follows for debugging:
printf("CMD:%d \n", rx_buff[0]);
printf("BUF1: %d \n", rx_buff[1]);
printf("BUF2: %d \n\n", rx_buff[2]);
However, I am pretty sure this is not the best/optimized way to handle multiple bytes from SPI, therefore, if there is an alternative, share...
I'm struggling with, probably, a very simple problem.
I have a Cypress CY8 controller acting as SPI master, which should communicate with a PIC32mx in slave mode to exchange data packets.
However i cannot even fix simple transmission of multiple bytes from the master to the slave. I've set up the cypress to transmit a char of increasing value (0-255) with a pause (and slave select toggle) in between. The pic should read the incoming byte and then print it over uart to my pc (the uart connection works).
But the pic only prints the first character it receives continuously instead of it being updated.
If i check my logic sniffer, the cypress does send incrementing values and the pic relays them back over the MISO line (looks like the shift buffer isn't cleared).
What could this be?
The cypress without the pic attached gives proper output:
https://dl.dropboxusercontent.com/u/3264324/Schermafdruk%202015-07-28%2015.43.28.png
With the pic attached it relays the data over MISO:
https://dl.dropboxusercontent.com/u/3264324/Schermafdruk%202015-07-28%2015.43.45.png
And this is my (now) extremely basic code to test it:
TRISBbits.TRISB2 = 1; // make Ra2 pin input (SDI)
TRISBbits.TRISB5 = 0; // make Ra2 pin output (SDO)
TRISBbits.TRISB15 = 1; //make RB14 output (SCK)
ANSELA = 0; // all ports digital
ANSELB = 0; // all ports digital
SYSKEY = 0x00000000;
SYSKEY = 0xAA996655;
SYSKEY = 0x556699AA;
CFGCONbits.IOLOCK=0; // unlock configuration
CFGCONbits.PMDLOCK=0;
SDI2R = 0b0100; //SDI2 on pin RB2
SS2R = 0b0011; //SS2 on pin rb10
RPB5R = 0b0100; //SDO2 on pin RB5
// SCLK is connected to pin RB14 (SCK) by default
SYSKEY = 0x00000000;
SPI2CON = 0; // Stops and resets the SPI1.
rData=SPI2BUF; // clears the receive buffer
SPI2BRG=207; // use FPB/4 clock frequency <-- not important in slave mode right?
SPI2STATCLR=0x40; // clear the Overflo
SPI2CON=0x8180;
unsigned char t;
while(1){
t = SpiChnReadC(2);
//t = SPI2BUF; <== i've tried this also
sendData(t); <== uart routine
}
As i do receive a character and the spi data is relayed back to the cypress constantly i think something goed wrong with reading/clearing the spi data structure in the PIC. But i can't figure out why.
As i read in the datasheet, reading from SPI2BUFF gives me the received data, and clears the read flags so new data can be received, but it looks like that doesn't happen...
Can someone shine a light on this for me?
Thanks in advance
Timberleek
You should try making you SPI handler ISR driven to keep you from constantly polling, can also help the debugging since you'll only get notifications when the SPI is actually transacting.
NOTE: I'm bringing this from my FreeRTOS impl, so my ISR definition is not XC32 exactly...
/* Open SPI */
SPI1CON = 0;
spi_flags = SPICON_MODE32 | SPICON_ON;
SpiChnOpen(1,spi_flags,BRG_VAL);
SpiChnGetRov(1,TRUE);
mSPI1ClearAllIntFlags();
mSPI1SetIntPriority(priority + 1);
mSPI1SetIntSubPriority(0);
mSPI1RXIntEnable(1);
void vSPI1InterruptHandler(void)
{
unsigned long data;
if (IFS0bits.SPI1EIF == 1)
{
mSPI1EClearIntFlag();
}
if (IFS0bits.SPI1RXIF == 1)
{
data = SPI1BUF;
//sendData(data);
}
mSPI1RXClearIntFlag();
}
I'm trying to develop a interface SPI and I have started with a simple configuration.
The question is that SCK seems to work fine but MOSI doesnt works.
Here is my code and my test logical tester.
#include <stdlib.h>
#include <plib.h>
// example functions prototypes
int SpiDoMasterSlaveExample(int nCycles);
void SpiInitDevice(int chn, int isMaster, int frmEn, int frmMaster);
// some definitions
#define MIN_SPI_TXFER_SIZE 8 // min number of words per transfer
#define MAX_SPI_TXFER_SIZE 512 // max number of words per transfer
// configuration settings
#pragma config FNOSC = PRIPLL, POSCMOD = HS, FPLLMUL = MUL_18, FPLLIDIV = DIV_2, FPBDIV = DIV_2, FPLLODIV = DIV_1
#pragma config FWDTEN = OFF
int main(void)
{
SYSTEMConfigPerformance(72000000L);
srand(ReadCoreTimer()); // seed the pseudo random generator
if(!SpiDoMasterSlaveExample(100))
{
return 0; // our example failed
}
return 1;
}
int SpiDoMasterSlaveExample(int nCycles)
{
int fail=0; // overall result
SpiInitDevice(1, 1, 1, 1); // initialize the SPI channel 1 as master, frame master
SpiInitDevice(2, 0, 1, 0); // initialize the SPI channel 2 as slave, frame slave
while(nCycles-- && !fail)
{
unsigned int txferSize;
unsigned short* pTxBuff;
unsigned short* pRxBuff;
txferSize=MIN_SPI_TXFER_SIZE+rand()%(MAX_SPI_TXFER_SIZE-MIN_SPI_TXFER_SIZE+1); // get a random transfer size
pTxBuff=(unsigned short*)malloc(txferSize*sizeof(short));
pRxBuff=(unsigned short*)malloc(txferSize*sizeof(short)); // we'll transfer 16 bits words
if(pTxBuff && pRxBuff)
{
unsigned short* pSrc=pTxBuff;
unsigned short* pDst=pRxBuff;
int ix;
int rdData;
for(ix=0; ix<txferSize; ix++)
{
pTxBuff[ix]='A'; // fill buffer with some random data
}
ix=txferSize+1; // transfer one extra word to give the slave the possibility to reply back the last sent word
while(ix--)
{
SpiChnPutC(1, *pSrc++); // send data on the master channel, SPI1
rdData=SpiChnGetC(1); // get the received data
if(ix!=txferSize)
{ // skip the first received character, it's garbage
*pDst++=rdData; // store the received data
}
rdData=SpiChnGetC(2); // receive data on the slave channel, SPI2
SpiChnPutC(2, rdData); // relay back data
}
// now let's check that the data was received ok
pSrc=pTxBuff;
pDst=pRxBuff;
for(ix=0; ix<txferSize; ix++)
{
if(*pDst++!=*pSrc++)
{
fail=1; // data mismatch
break;
}
}
}
else
{ // memory allocation failed
fail=1;
}
free(pRxBuff);
free(pTxBuff); // free the allocated buffers
}
return !fail;
}
void SpiInitDevice(int chn, int isMaster, int frmEn, int frmMaster)
{
unsigned int config=SPI_CON_MODE16|SPI_CON_SMP|SPI_CON_ON; // SPI configuration word
if(isMaster)
{
config|=SPI_CON_MSTEN;
}
if(frmEn)
{
config|=SPI_CON_FRMEN;
if(!frmMaster)
{
config|=SPI_CON_FRMSYNC;
}
}
SpiChnOpen(chn, config, 4); // divide fpb by 4, configure the I/O ports. Not using SS in this example
}
Sorry, I can't post the logical analyser image for my reputation points.
I'm trying to send "A" all time (fill buffer transmit). That's send data to SPI1.
I'm reading SPI1 from my Microchip Expansion Board I/O where SPI1 is in pins 41 and 43 (41 SCK and 43 SDO).
In SPI2, pin 23 and 25, obviously I have not any traffic.
Does anyone have idea of this error?
Thanks a lot
The PIC32MX series has mapable input and output pins for some peripherals, including the SPI. This means, that MOSI and MISO can be mapped to different pins, depending on your specific needs.
You need to specify this in code before you start using the SPI, otherwise, the PIC won't know which pins to use.
The following is just an example of how to setup the pins (peripheral pin select). You need to look in your PIC's datasheet for the mappings. The first parameter in the calls is the table index from the datasheet.
/* inputs */
PPSInput(2, SDI1, RPF2); // F2, MEMORY MISO -> SPI1SDI
PPSInput(2, SDI2, RPG7); // G7, ZB MISO -> SPI2SDI
/* outputs */
PPSOutput(4, RPF3, SDO1); // F3, MEMORY MOSI -> SPI1SDO
PPSOutput(1, RPG8, SDO2); // G8, ZB MOSI -> SPI2SDO
As described before, check your peripheral pin select. Additional you must set your port direction to Output (PDx-Register). MISO must be set to an Input.