How to send 1 byte as 8 bits

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
BUTA_1301626
Level 4
Level 4
50 replies posted 25 replies posted 10 replies posted

I have a TX pin. I want to send hexadecimal AA information to this pin. When I look at the logic analyzer, I want to see the logic of 10101010. How can I do that?

0 Likes
1 Solution
lock attach
Attachments are accessible only for community members.
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

Although Sending and Receiving Serial data by firmware need a couple of MCUs, this topic is in PSoC 6 Forum!

And a PSoC 6 often has a couple of cores, Cortex-M0+ and Cortex-M4.

So I tried let Cortex-M4 send bytes, and let Cortex-M0+ to receive them.

It's great that we can test with only a single board 😉

I used CY8CKIT-062-WIFI-BT

The schematic was (connect P0[2] and P5[6] to let cores communicate)

001-schematic.JPG

002-PinList.JPG

Cortex-M0+ main.c

=================

#include "project.h"

#include "stdio.h"

#define BIT_DELAY 10

#define SW_LOW  (0u)

#define SW_HIGH (1u)

#define delay(a)  CyDelayUs(a)

char str[128] ; /* print buffer */

void print(char *str)

{

    UART_PutString(str) ;

}

void init_hardware(void)

{

    __enable_irq(); /* Enable global interrupts. */

    UART_Start() ;

    /* Enable CM4.  CY_CORTEX_M4_APPL_ADDR must be updated if CM4 memory layout is changed. */

    Cy_SysEnableCM4(CY_CORTEX_M4_APPL_ADDR);  

}

void splash(void)

{

    sprintf(str, "Software Serial Test (%s %s)\n", __DATE__, __TIME__) ;

    print(str) ;

}

uint8_t sw_recv_byte(void)

{

    int bit_count = 8 ;

    uint8_t data = 0 ;

  

    while(Cy_GPIO_Read(SW_RX_0_PORT, SW_RX_0_NUM) == SW_HIGH) {

        delay(BIT_DELAY/2) ;

    }

    delay(BIT_DELAY) ;

    while(bit_count--) {

        data <<= 1 ;

        if (Cy_GPIO_Read(SW_RX_0_PORT, SW_RX_0_NUM) == SW_HIGH) {

            data |= 0x01 ;

        }

        delay(BIT_DELAY) ;

    }

    if (Cy_GPIO_Read(SW_RX_0_PORT, SW_RX_0_NUM) != SW_HIGH) {

        print("SW_RX, Stop bit missing!\n") ;

    }

    return( data ) ;

}

int main(void)

{

    uint8_t data = 0 ;

  

    init_hardware() ;

  

    splash() ;

    for(;;)

    {

        data = sw_recv_byte() ; /* this function blocks */

        sprintf(str, "\tCM0 received 0x%02X\n", data) ;

        print(str) ;

    }

}

=================

Cortex-M4 main.c

=================

#include "project.h"

#include "stdio.h"

char str[128] ; /* print buffer */

void print(char *str)

{

    UART_PutString(str) ;

}

#define BIT_DELAY 10

#define SW_LOW  (0u)

#define SW_HIGH (1u)

#define delay(a)  CyDelayUs(a)

void sw_send_byte(uint8_t byte_to_send)

{

    uint8_t mask = 0x80 ;

    Cy_GPIO_Write(SW_TX_0_PORT, SW_TX_0_NUM, SW_LOW) ; /* start bit wannabe */

    delay(BIT_DELAY) ;

    while(mask) { /* sending 8 bits MSB first */

        if (byte_to_send & mask) {

            Cy_GPIO_Write(SW_TX_0_PORT, SW_TX_0_NUM, SW_HIGH) ;

        } else {

            Cy_GPIO_Write(SW_TX_0_PORT, SW_TX_0_NUM, SW_LOW) ;

        }

        mask >>= 1 ;

        delay(BIT_DELAY) ;

    }

    Cy_GPIO_Write(SW_TX_0_PORT, SW_TX_0_NUM, SW_HIGH) ;  

    delay(BIT_DELAY) ; /* stop bit wannabe */

}

int main(void)

{

    uint8_t byte_to_send = 0x00 ;

  

    __enable_irq(); /* Enable global interrupts. */

    Cy_GPIO_Write(SW_TX_0_PORT, SW_TX_0_NUM, SW_HIGH) ;

  

    CyDelay(1000) ; /* wait for Cortex-M0 to be ready, may be too much */

    for(;;)

    {

        sprintf(str, "CM4 sending 0x%02X\n", byte_to_send) ;

        print(str) ;

        sw_send_byte(byte_to_send) ;

        byte_to_send = (byte_to_send + 1) % 0x100 ;

        CyDelay(1000) ;

    }

}

=================

The debug output via Tera Term was

000-TeraTerm-log.JPG

As far as I tried, 2us for 1 bit did not work, but so far 10us for 1 bit seems to be working.

As usual, your mileage may vary

moto

P.S. Alas, this was the first program I intentionally used both cores of PSoC 6 orz

View solution in original post

0 Likes
17 Replies
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

You can use a UART component which will do all you want. Just UART_Start() and send your byte. Have a look at UART datasheet to see all the facilities offered.

Bob

0 Likes

When I use uart, the start and end bits are added.  I need to use uart. but I need to find a different solution because of the start and end bit.

0 Likes

Use a shift rergister component.

Bob

0 Likes

I wrote it here because I didn't know how to do it with Shift Register.

I'd appreciate it if you help.

0 Likes

I just see that there is no shift register in PSoC6. Makes things right complicated. Someone else has to jump in to solve that problem.

Bob

0 Likes
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

Assuming that we can Write to TX pin by TX_Write(value),

If I may write it in a program, it will look like

===============

void serialize(uint8_t theByte)

{

    uint8_t mask = 0x80 ; /* 1000_0000 */

    while(mask) {

      if (theByte & mask) {

          TX_Write(1) ;

       } else {

          TX_Write(0) ;

       }

      mask >>= 1 ;

      CyDelayUs(1) ; // adjust delay for your purpose

    }

}

===============

moto

void serialize(uint8_t theByte)

{

    uint8_t mask = 0x80 ; /* 1000_0000 */

    while(mask) {

      if (theByte & mask) {

          TX_Write(1) ;

       } else {

          TX_Write(0) ;

       }

      mask >>= 1 ;

      CyDelayUs(1) ; // adjust delay for your purpose

    }

}

it works only if I use the tx pin. but does not work when connected to uart_1.I want to send both data only to the pin tx (uart data = start bit data stop bit). So I want it to work when connected to uart_1.

Ekran Alıntısı2.JPG

0 Likes
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

In your question you wrote 0xAA -> 10101010

this is called "MSB First"

But usually UART sends "LSB First", wihch means

if you use UART_1_PutChar(0xAA) ;

tx pin will generate (start bit) 01010101 (stop bit)

So you must convert your data from 0xAA to 0x55 before calling UART_1_PutChar(data) ;

Except this, you can send byte data by

(1) call UART_1_Start() at the beginning of your program

(2) put data with reversed bit order

(3) then call UART_1_PutChar(data) ;

If your application can put up with LSB First you don' t have to do (2)

moto

0 Likes
Hari
Moderator
Moderator
Moderator
750 replies posted 500 replies posted 250 solutions authored

Hello

Can you please elaborate your requirement? When a UART block is connected to a pin, the start and stop bits are added since the protocol requires that.

If you wish to toggle a pin, it should not be connected to the UART block and must be a software driven pin (Hardware connection should be disabled).

Please let us know the exact requirement so that we can suggest the suitable solution.

Regards

Harigovind

Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Most problem you will tun into is to indicate to the receiver that a transmission is about to start (synchronization). This will requre an additional pin or a construct like start/stop bits.

For the latter case an UART will bw best, for the former one an SPI interface does exactly what you need.

Bob

0 Likes

is it possible to do the opposite of this process?

that is, converting bits (8 bits ==> bytes) to bytes.

0 Likes

Can be done with a SPI component as well. Think about how it must work: There will be the data signal, there must be a clock to indicate the bit positions within the data stream and there should be a signal to indicate the byte boundaries to synchronize the data stream. All this is maintained within the SPI protocol.

Bob

0 Likes

I tried it with SPI. He's working. I'm wondering how I can do that by writing code.

Is there a problem in the code below?

uint8 DATA()

{

uint8 DATABIT = 0x08;

uint8 RF0=0;

RF0 = RF0 << 1;

if (DIO_Read())

RF0 = RF0 | 0x01;

else

RF0 = RF0 & 0xFE;

while(--DATABIT);

return(RF0);

}

0 Likes
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

As Bob-san stated, you need a way to detect when data started.

Otherwise constant low pin is read as 0x00 and constant high pin will be read as 0xFF.

So in the serial communication, there have been many methods invented.

IMHO, there are (at least) two groups of methods,

(1) include start information in the data

(2) provide other signal(s) to indicate the start and/or the speed.

UART takes  the strategy (1) , it keeps the signal high while idle

then it uses start bit (which is a transition from high to low)

and added a stop bit (let me make it simple here)

On the other hand, SPI takes the strategy (2),

it provides SCLK (clock).

So if I add (1) to my previous code it will look like

Note:

To take care of the receiver, the delay is 2 us for this sample.

And I'm assuming both are running same or very close clock.

I have not tested these so you may (must) need to debug...

============

void serialize(uint8_t theByte)

{

    uint8_t mask = 0x80 ; /* 1000_0000 */

    TX_Write(1) ; /* TX should be 1 before sending anyway */

    CyDelayUs(2) ;

    while(mask) {

      if (theByte & mask) {

          TX_Write(1) ;

       } else {

          TX_Write(0) ;

       }

      mask >>= 1 ;

      CyDelayUs(2) ; // adjust delay for your purpose

    }

    TX_Write(2) ; /* Resume TX to idle state */

}

============

Or if I add (2)

============

// assuming we have TX_VALID gpio pin

void serialize(uint8_t theByte)

{

    uint8_t mask = 0x80 ; /* 1000_0000 */

     TX_VALID_Wirte(0) ; /* must have been 0 though */

     CyDelayUs(2) ;

     TX_VALID_Write(1) ;

    CyDelayUs(2) ;

    while(mask) {

      if (theByte & mask) {

          TX_Write(1) ;

       } else {

          TX_Write(0) ;

       }

      mask >>= 1 ;

      CyDelayUs(2) ; // adjust delay for your purpose

    }

    TX_VALID_Write(0) ; /* Resume TX to idle state */

}

============

Then de_serialize() will be

strategy (1)

===============

uint8_t de_serialize(void)

{

   uint8 DATABIT = 0x08;

   uint8 RF0=0;

    while(RX_Read() == 1) { /* wait for start bit */

         CyDelay(1)  ; /* note we are sampling 2x first */

    }

   // here we got the start bit

   do {

      CyDelay(2) ; /* wait 1 bit */

      RF0 = RF0 << 1;

      if (DIO_Read()) {

          RF0 = RF0 | 0x01;

       } else {

          RF0 = RF0 & 0xFE;

      }

   } while(--DATABIT);

   return(RF0);

}

===============

strategy (2)

Note: Assming the TX_VALID signal is connected to an input pin RX_VALID.

===============

uint8_t de_serialize(void)

{

   uint8 DATABIT = 0x08;

   uint8 RF0=0;

    while(RX_VALID_Read() == 0) { /* wait for start bit */

         CyDelay(1)  ; /* note we are sampling 2x first */

    }

   // here we received the data valid

   do {

      CyDelay(2) ; /* wait 1 bit */

      RF0 = RF0 << 1;

      if (DIO_Read()) {

          RF0 = RF0 | 0x01;

       } else {

          RF0 = RF0 & 0xFE;

      }

   } while(--DATABIT);

   return(RF0);

}

===============

But, after all using SPI or UART is much more practical 😉

moto

I'm trying the following program. but the program does not run. I did the debug check.

5 bytes 0x00 = 40 bit LOW                                   /

4 bytes 0xFF and 1 byte 0xFE = 39 bit HIGH    / ==>I'm trying to check this  information.

If this information is correct, I am trying to load the information that follows. but it's not working.

uint8 CHECKSENC()

{

uint8 counthigh=0, countlow=0, SAY,iSay;

for(iSay =0; iSay < 2; iSay++) {

SAY = 0;

  SAY++;

if (!SW_Read()) {

if ((counthigh > 37) && (countlow > 38)) {

  return(1);

}

counthigh = 0;

countlow++;

}

else {

if (countlow < 38) {

countlow = 0;

return(0);

}

counthigh++;

}

  while(SAY != 250);

}

return (0);

}

uint8 DATAOKURF(void)

{

uint8 DATABIT = 0x08;

uint8 RF0=0;

RF0 = RF0 << 1;

if (DIO_Read())

RF0 = RF0 | 0x01;

else

RF0 = RF0 & 0xFE;

while(--DATABIT);

return(RF0);

}

int main(void)

{

    CyGlobalIntEnable; /* Enable global interrupts. */

LCD_Start();

CH_Write(1u);

TR_Write(1u);

CyDelay(100);

    for(;;)   {

while(1){

do{

ISYNC = CHECKSENC();

}

while(!ISYNC);

for(count=0; count < 10 ; count++)

{

RFBuffer[count] = DATAOKURF();

}

/* [] END OF FILE */

    }}

0 Likes
Hari
Moderator
Moderator
Moderator
750 replies posted 500 replies posted 250 solutions authored

Hi

In the code that is shared, the program will run into an infinite loop as the values are overwritten on each function call. That is, the variable countlow will never reach 38 and SAY will not reach 250 and this will cause the function to be stuck in an infinite loop.

For the use-case that you have mentioned, please consider this article Controlling UART Tx and Rx Pins through Firmware for PSoC 4 Devices - KBA 224950 which explains the procedure to control UART pins through firmware when required and as UART pins otherwise.

Do let us know in case of any further issues.

Thanks and regards

Harigovind

0 Likes
lock attach
Attachments are accessible only for community members.
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

Although Sending and Receiving Serial data by firmware need a couple of MCUs, this topic is in PSoC 6 Forum!

And a PSoC 6 often has a couple of cores, Cortex-M0+ and Cortex-M4.

So I tried let Cortex-M4 send bytes, and let Cortex-M0+ to receive them.

It's great that we can test with only a single board 😉

I used CY8CKIT-062-WIFI-BT

The schematic was (connect P0[2] and P5[6] to let cores communicate)

001-schematic.JPG

002-PinList.JPG

Cortex-M0+ main.c

=================

#include "project.h"

#include "stdio.h"

#define BIT_DELAY 10

#define SW_LOW  (0u)

#define SW_HIGH (1u)

#define delay(a)  CyDelayUs(a)

char str[128] ; /* print buffer */

void print(char *str)

{

    UART_PutString(str) ;

}

void init_hardware(void)

{

    __enable_irq(); /* Enable global interrupts. */

    UART_Start() ;

    /* Enable CM4.  CY_CORTEX_M4_APPL_ADDR must be updated if CM4 memory layout is changed. */

    Cy_SysEnableCM4(CY_CORTEX_M4_APPL_ADDR);  

}

void splash(void)

{

    sprintf(str, "Software Serial Test (%s %s)\n", __DATE__, __TIME__) ;

    print(str) ;

}

uint8_t sw_recv_byte(void)

{

    int bit_count = 8 ;

    uint8_t data = 0 ;

  

    while(Cy_GPIO_Read(SW_RX_0_PORT, SW_RX_0_NUM) == SW_HIGH) {

        delay(BIT_DELAY/2) ;

    }

    delay(BIT_DELAY) ;

    while(bit_count--) {

        data <<= 1 ;

        if (Cy_GPIO_Read(SW_RX_0_PORT, SW_RX_0_NUM) == SW_HIGH) {

            data |= 0x01 ;

        }

        delay(BIT_DELAY) ;

    }

    if (Cy_GPIO_Read(SW_RX_0_PORT, SW_RX_0_NUM) != SW_HIGH) {

        print("SW_RX, Stop bit missing!\n") ;

    }

    return( data ) ;

}

int main(void)

{

    uint8_t data = 0 ;

  

    init_hardware() ;

  

    splash() ;

    for(;;)

    {

        data = sw_recv_byte() ; /* this function blocks */

        sprintf(str, "\tCM0 received 0x%02X\n", data) ;

        print(str) ;

    }

}

=================

Cortex-M4 main.c

=================

#include "project.h"

#include "stdio.h"

char str[128] ; /* print buffer */

void print(char *str)

{

    UART_PutString(str) ;

}

#define BIT_DELAY 10

#define SW_LOW  (0u)

#define SW_HIGH (1u)

#define delay(a)  CyDelayUs(a)

void sw_send_byte(uint8_t byte_to_send)

{

    uint8_t mask = 0x80 ;

    Cy_GPIO_Write(SW_TX_0_PORT, SW_TX_0_NUM, SW_LOW) ; /* start bit wannabe */

    delay(BIT_DELAY) ;

    while(mask) { /* sending 8 bits MSB first */

        if (byte_to_send & mask) {

            Cy_GPIO_Write(SW_TX_0_PORT, SW_TX_0_NUM, SW_HIGH) ;

        } else {

            Cy_GPIO_Write(SW_TX_0_PORT, SW_TX_0_NUM, SW_LOW) ;

        }

        mask >>= 1 ;

        delay(BIT_DELAY) ;

    }

    Cy_GPIO_Write(SW_TX_0_PORT, SW_TX_0_NUM, SW_HIGH) ;  

    delay(BIT_DELAY) ; /* stop bit wannabe */

}

int main(void)

{

    uint8_t byte_to_send = 0x00 ;

  

    __enable_irq(); /* Enable global interrupts. */

    Cy_GPIO_Write(SW_TX_0_PORT, SW_TX_0_NUM, SW_HIGH) ;

  

    CyDelay(1000) ; /* wait for Cortex-M0 to be ready, may be too much */

    for(;;)

    {

        sprintf(str, "CM4 sending 0x%02X\n", byte_to_send) ;

        print(str) ;

        sw_send_byte(byte_to_send) ;

        byte_to_send = (byte_to_send + 1) % 0x100 ;

        CyDelay(1000) ;

    }

}

=================

The debug output via Tera Term was

000-TeraTerm-log.JPG

As far as I tried, 2us for 1 bit did not work, but so far 10us for 1 bit seems to be working.

As usual, your mileage may vary

moto

P.S. Alas, this was the first program I intentionally used both cores of PSoC 6 orz

0 Likes