Can someone help me with OS 6xx serial functions (using Mbed Studio)?
Mbed continuing to redesign the wheel, I was hoping they had got bored by now
I’m updating from earlier versions with serial put and get but hit a small snag.
Sending a bunch of characters is okay but,
To send a single byte or character I’m using this:
oled.write((char*)0x55,1); // send byte for OLED to autodetect baudrate
No red or yellow squiggly underlines with that so it might work, can’t tell until I’ve fixed the rest of the code.
However one function needs some extra bit manipulation, last two commands, not sure if I can do this inside the command or if I have to handle it outside…
void OLED160G1::drawLine(char x1, char y1, char x2, char y2, int color) {
oled.write(OLED_LINE); // Line
oled.write(x1);
oled.write(y1);
oled.write(x2);
oled.write(y2);
oled.write(color >> 8); // MSB stuck here
oled.write(color & 0xFF); // LSB and here
getResponse();
}
That looks a bit more os6 compliant. I’ll try that and later but this is far as I got, but not working.
Can’t seem to get serial interrupt callback working like before.
OLED160G1::OLED160G1(PinName serialTx, PinName serialRx, PinName resetPin)
: Oled(serialTx, serialRx), reset(resetPin) {
Oled.baud(BAUDRATE);
Oled.format(8, // bits
SerialBase::None, // parity
1 // stop bit
);
resetDisplay();
}
void OLED160G1::oledcb() { // serial callback if serial port receives data
while (Oled.readable()){
Oled.read(&oledbuff[bufferIndex],1);
bufferIndex++;
}
oledrx=1;
}
void OLED160G1::resetDisplay() {
char c;
reset = 0;
wait_us(10000);
reset = 1;
wait_us(500000);
while (Oled.readable()){
Oled.read(&c,1);
}
c = 0x55;
Oled.attach(callback(this,&OLED160G1::oledcb),SerialBase::RxIrq);
Oled.write(&c,1); // send byte for OLED to autodetect baudrate
getResponse();
setFontSize(FONT5X7);
setTextBackgroundType(TEXT_OPAQUE);
setFontColor(WHITE);
drawText(0,0,(FONT5X7),(char*)"Oled160g1",toRGB(100,100,100));
drawText(0,2,(FONT5X7),(char*)"Ready > ",toRGB(100,100,100));
}
void OLED160G1::getResponse() {
t.reset(); t.start();
while (chrono::duration_cast<chrono::milliseconds>(t.elapsed_time()).count() < 500) {
if (oledrx) {
oledrx = 0;
//debug("response: %d\n",oledbuff[0]);
if (oledbuff[0] == 6) { // 0x06 byte sent successful
break;
}
if (oledbuff[0] == 21) { // 0x15 byte sent unsuccessful
break;
}
}
}
bufferIndex=0;
t.stop();
return;
}
The only part of your code that I find problematic is the oledcb() function.
It’s an IRQ function so there is nothing blocking it.
It is triggered with each received character, so there is no need to loop or test the return of readable().
void OLED160G1::oledcb() { // serial callback if serial port receives data
Oled.read(&oledbuff[bufferIndex++],1);
oledrx=1;
}
For what it’s worth, this is actually a good use case for the new Mbed 6 asynchronous buffered serial.
You can actually completely remove the attach() call and the callback, and replace your waiting loop with something like this:
while (chrono::duration_cast<chrono::milliseconds>(t.elapsed_time()).count() < 500) {
while (Oled.readable()){
// read a byte using Oled.read() and process it
}
}
You will also need to make sure Oled is a BufferedSerial and set it to nonblocking mode, e.g. by adding this to the constructor:
This goes back a while so I thought I would have another go.
All the suggestions were very helpful, thank you.
I now have it working reliably.
I’m using Nucleo L476, mbed-os 6.16.0, Mbed Studio.
The L476 didn’t like baud rates above 128k, where the F401 works stable up to 256k, the displays maximum rate. A bit strange, the L476 RM states up to 10Mbps with oversampling and I’m sure I’ve used this MCU serial up to 921600Bps on OS2.
The snip bellow does work, different display but same serial interface .
Problem I have using Unbuffered Serial is serial.read() is blocking no matter what I do.
With or without oled.set_blocking(false) , if there is no serial data the program hangs when it reaches it.
I do not need Buffered Serial particularly because I know when and how much data is being sent/received for each command.
So to get round this problem I used a timer to timeout oled.readable() after 100mS.
Now if there is a break in serial communication to the display for any reason it does not lock up the MCU and I can recover the display function.
bool oled32028::getResponse() {
int ready = false;
t.reset();
while (!ready && t.elapsed_time().count() < 100000) { // 100mS timeout
while (oled.readable()) {
oled.read(&c, 1);
ready = true;
}
}
if (c == 0x06) { // byte sent successful
// debug_if(dbg_on, "Okay c: %d\n", c);
return 1;
}
if (c == 0x15) { // byte sent unsuccessful
//debug_if(dbg_on, "Fail c: %x\n", c);
}
return 0; // timeout, fail
}
This proved the most efficient way to send data to the display;
oooh, the advantage of chrono is that you can deal directly with time units. Peeling of the count and comparing against unknown integer units is so ugly…