前言
感芯科技推出了一款64线程的MCU,此前在感芯科技的公众号申请了一块免费的开发板,进行了简单的评测使用,整体上使用体验良好。首先这款开发板的特性是64线程,高实时和高确定性,其线程频率由内部时钟静态片分,换言之就是线程逻辑上独立,适用于高实时的应用场景——它就是 MC3172
。
基础信息
这块开发板目前已经调试过PWM呼吸灯,UART,SPI,OLED亮屏等功能,整体上手难度一般,开发板图例如下,更多相关信息请前往文章底部进入开发板官网链接进行查看:
点亮OLED
本次例程针对SH1106,这块OLED采用SPI协议,屏幕大小为1.3英寸,分辨率为128 * 64。
话不多说,直接上代码:
/* LED 128*64 7 PINs SPI Protocal Driver
* @Date 2022-07-16
* @Author Winter
* @License Apache Licence 2.0
*/
#include "MC3172.h"
#define OLED_COLUMN_NUMBER 128 // Screen resolution width
#define OLED_ROW_NUMBER 64 // Screen resolution height
#define OLED_COLUMN_OFFSET 2
#define OLED_PAGE_NUMBER OLED_ROW_NUMBER / 8 // how many pages to divide ROW
#define OLED_POS_PORT GPIOC_BASE_ADDR
#define OLED_GPCOM_PORT GPCOM9_BASE_ADDR
#define OLED_GPCOM_TX_RP GPCOM9_TX_RP
#define OLED_GPCOM_TX_WP GPCOM9_TX_WP
static u8 video_buffer[1024]; // Video Memory
// RST(RES): Reset Signal Input, High for normal operation
// Position: PORTC[2]
#define SET_SPI_RST_0 GPIO_SET_OUTPUT_PIN_TO_0(OLED_POS_PORT, (GPIO_PIN2))
#define SET_SPI_RST_1 GPIO_SET_OUTPUT_PIN_TO_1(OLED_POS_PORT, (GPIO_PIN2))
// DC: Data/Command Control
// Position: PORTC[5]
#define SET_SPI_DC_0 GPIO_SET_OUTPUT_PIN_TO_0(OLED_POS_PORT, (GPIO_PIN5))
#define SET_SPI_DC_1 GPIO_SET_OUTPUT_PIN_TO_1(OLED_POS_PORT, (GPIO_PIN5))
// CS: Chip Select
// Position: PORTC[4]
#define SET_SPI_CS_0 GPIO_SET_OUTPUT_PIN_TO_0(OLED_POS_PORT, (GPIO_PIN4))
#define SET_SPI_CS_1 GPIO_SET_OUTPUT_PIN_TO_1(OLED_POS_PORT, (GPIO_PIN4))
// SH1106 commands for SPI
const unsigned char _init_cmd[25] = {
0xAE, //Set display off
0xD5, //Set frequency division
0x80, //[3:0],Set display divide ratio;[7:4],(OSC drequency)
0xA8, //Set multiplex ratio.
0X3F, //default is 1/64
0xD3, //Set display offset
0X00, //default is 0
0x40, //set display start line [5:0]
0x8D, //Set charge pump
0x14,
0x20, //Set address mode
0x02, //[1:0],00,column first;01,row first;10,page first;default is 10;
0xA1, //Set segment Re-map,bit0:0,0->0;1,0->127;
0xC8, //Set COM output scan direction,bit3:0,normal mode;1,redefine mode COM[N-1]->COM0;N:driver channeles (C0 display inverse) C8
0xDA, //Set COM I/O
0x12, //[5:4]
0x81, // Set contrast
0x66, // Set brightness, 1~255;default is 0X7F
0xD9, //Set pre-charge period
0xf1, //[3:0],PHASE 1;[7:4],PHASE 2;
0xDB, //Set VCOMH deselect level
0x30, //[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc;
0xA4, //Set entire display on/off ;bit0:1,on;0,off;
0xA6, //Set display mode;bit0:1,Normal;0,Inverse
0xAF, //Set display on
};
void _oled_init_io(void)
{
// CS:PORTC[4] DC:PORTC[5] RES:PORTC[2] SDA:PORTC[6] SCK:PORTC[7]
INTDEV_SET_CLK_RST(OLED_POS_PORT, (INTDEV_RUN | INTDEV_IS_GROUP0 | INTDEV_CLK_IS_CORECLK_DIV32)); // 133/32
GPIO_SET_OUTPUT_EN_VALUE(OLED_POS_PORT, (GPIO_PIN2 | GPIO_PIN3 | GPIO_PIN4 | GPIO_PIN5), GPIO_SET_ENABLE);
INTDEV_SET_CLK_RST(OLED_GPCOM_PORT, (INTDEV_RUN | INTDEV_IS_GROUP0 | INTDEV_CLK_IS_CORECLK_DIV32));
GPCOM_SET_OUT_PORT(OLED_GPCOM_PORT, (GPCOM_P0_OUTPUT_DISABLE | GPCOM_P1_OUTPUT_DISABLE | GPCOM_P2_OUTPUT_ENABLE | GPCOM_P2_IS_MASTER_OUT | GPCOM_P3_OUTPUT_ENABLE | GPCOM_P3_IS_MASTER_CLK));
GPCOM_SET_COM_MODE(OLED_GPCOM_PORT, (GPCOM_SPI_MASTER_MODE0 | GPCOM_TX_MSB_FIRST | GPCOM_RX_MSB_FIRST));
GPCOM_SET_COM_SPEED(OLED_GPCOM_PORT, 4156250, 1000000);
GPCOM_SET_OVERRIDE_GPIO(OLED_GPCOM_PORT, (GPCOM_P2_OVERRIDE_GPIO | GPCOM_P3_OVERRIDE_GPIO));
}
void _oled_send_byte(unsigned char byte)
{
u8 tx_data_wp = 0;
tx_data_wp = GPCOM_GET_TX_WP(OLED_GPCOM_PORT);
GPCOM_SEND_TX_DATA(OLED_GPCOM_PORT, tx_data_wp + 0, byte); // Write data to cache 0 buffer.
tx_data_wp += 1;
GPCOM_SEND_TX_WP(OLED_GPCOM_PORT, tx_data_wp);
while (OLED_GPCOM_TX_RP != OLED_GPCOM_TX_WP)
{ // waiting for transmission
};
} // SPI_SendByte
void _oled_send_cmd(unsigned char o_command)
{
SET_SPI_DC_0;
SET_SPI_CS_0;
_oled_send_byte(o_command);
SET_SPI_CS_1;
// SPI_DC_1;
}
void _oled_send_data(unsigned char o_data)
{
SET_SPI_DC_1;
SET_SPI_CS_0;
_oled_send_byte(o_data);
SET_SPI_CS_1;
}
void _oled_set_column(unsigned char column)
{
column += OLED_COLUMN_OFFSET;
_oled_send_cmd(0x10 | (column >> 4)); //Setting the column higher bits.
_oled_send_cmd(0x00 | (column & 0x0F)); //Setting the column lower bits.
}
void _oled_set_page(unsigned char page)
{
_oled_send_cmd(0xb0 + page);
}
void _oled_clear(void)
{
unsigned char page, column;
for (page = 0; page < OLED_PAGE_NUMBER; page++) // page loop
{
_oled_set_page(page);
_oled_set_column(0);
for (column = 0; column < OLED_COLUMN_NUMBER; column++) // column loop
{
_oled_send_data(0x00);
}
}
}
void _oled_fullfilled(void)
{
unsigned char page, column;
for (page = 0; page < OLED_PAGE_NUMBER; page++) // page loop
{
_oled_set_page(page);
_oled_set_column(0);
for (column = 0; column < OLED_COLUMN_NUMBER; column++) // column loop
{
_oled_send_data(0xff);
}
}
}
void _oled_init_cmds(void)
{
unsigned char i;
for (i = 0; i < 25; i++)
{
_oled_send_cmd(_init_cmd[i]);
}
}
void _frame_refresh(const unsigned char *ptr_pic)
{
unsigned char page, column;
for (page = 0; page < (OLED_ROW_NUMBER / 8); page++) // page loop
{
_oled_set_page(page);
_oled_set_column(0);
for (column = 0; column < OLED_COLUMN_NUMBER; column++) // column loop
{
_oled_send_data(*ptr_pic++);
}
}
}
void _frame_refresh_inverse(const unsigned char *ptr_pic)
{
unsigned char page, column, data;
for (page = 0; page < (OLED_ROW_NUMBER / 8); page++) // page loop
{
_oled_set_page(page);
_oled_set_column(0);
for (column = 0; column < OLED_COLUMN_NUMBER; column++) // column loop
{
data = *ptr_pic++;
data = ~data;
_oled_send_data(data);
}
}
}
int oled_init(void)
{
_oled_init_io();
SET_SPI_RST_0;
delay_ms(500);
SET_SPI_RST_1;
delay_ms(500);
_oled_init_cmds();
_oled_fullfilled();
delay_ms(500);
_oled_clear();
}
void oled_refresh()
{
_frame_refresh(&video_buffer[0]);
}
// Inverse the bit value for each pixel.
void oled_refresh_inverse()
{
_frame_refresh_inverse(&video_buffer[0]);
}
在以上的代码中video_buffer
为屏幕展示的内容,在此处提供一个内容帧用于验证参考:
//replace vide_buffer with below:
static u8 video_buffer[] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,8,56,248,96,0,0,0,0,0,0,0,0,0,0,128,128,192,64,64,64,96,32,32,32,32,96,64,64,64,192,128,128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,64,32,48,16,8,12,4,4,6,6,2,2,2,2,2,2,2,4,4,4,4,4,12,8,12,15,11,8,8,8,8,8,12,4,2,2,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,2,6,4,12,16,48,96,192,128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,248,14,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,224,240,224,0,0,0,0,0,0,0,0,0,128,96,32,0,0,0,0,0,0,192,128,224,76,246,112,244,200,200,240,240,112,144,32,0,0,0,0,0,1,6,56,192,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,224,32,32,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,15,15,0,0,0,0,0,0,224,28,3,0,0,0,0,192,224,48,250,63,239,247,187,217,239,255,123,28,7,11,1,2,0,0,0,0,0,0,0,0,0,224,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,255,176,240,255,240,128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,96,30,3,0,0,0,0,0,1,6,8,24,48,32,33,33,99,67,67,67,67,131,131,129,128,128,128,128,64,64,64,64,96,32,32,32,48,24,12,7,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,7,6,3,6,12,8,8,24,16,48,32,32,32,96,64,64,64,64,64,64,192,128,192,192,96,96,80,88,68,70,65,65,64,64,64,64,64,192,128,0,0,0,0,0,0,192,32,24,4,2,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,224,240,172,131,160,192,128,192,192,254,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,48,24,8,12,14,1,0,0,0,0,0,0,0,0,7,62,112,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
在代码中嵌入该帧内容,运行后你将会获得一个外星人版本的史努比!!!
扩展
笔者在以上基础上进行了扩展,实现了随画随显功能,效果如下图,有兴趣使用该开发板的网友可以尝试更多有意思的创意和体验。
结语
领取开发板至今大概有一个月时间,笔者在工作之余去体验了该开发板,最大的体验是多线程的无感调度(硬件实现),使用该特性可以实现更多需要高独立性高实时性的应用,一起期待更多有意思的创意吧!
更多内容相关
官方代码仓库:gxchip (gitee.com),官网:感芯科技