前言

感芯科技推出了一款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_WPstatic 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 SPIconst 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_SendBytevoid _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),官网:感芯科技