# stc8练习 **Repository Path**: dulht/stc8-exercise ## Basic Information - **Project Name**: stc8练习 - **Description**: No description available - **Primary Language**: C - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-09-08 - **Last Updated**: 2021-11-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: c51stc8g, stc8g ## README # stc8练习 ![stc8g](https://img.alicdn.com/imgextra/i4/2201499245706/O1CN01rF2vmA1s1OchQPwYc_!!2201499245706.png) ## 介绍 **stc8驱动学习**\ 存在问题: 1. ~~21年9月12日 接收端通过nrf24l01同时接收多个信号时一会就中断~~ 。9月14日更新解决[详见接收代码](https://gitee.com/dulht/dulc51/blob/master/nrf%20adc%20uart%200823/nrfRecv.c) 2. ## 注意事项 **进入掉电/停机模式前,所有未使用的外部悬空I/O口都需要设置为准双向口,并固定输出高电平。**\ 0 0 准双向口(传统IO)\ 0 1 推挽输出(强上拉 输出,电流可达20mA,尽量少用)\ 1 0 仅为输入(高阻,如ADC读取)\ 1 1 开漏,如传统8051的P0口\ *** 例如: P1M0 = 0xC0; P1M1 = 0xA0;//P1.7开漏,P1.6强推挽输出,P1.5高阻,其他准双向IO口。 如下: 7 6 5 4 3 2 1 0 P1M0 = 1 1 0 0 0 0 0 0 P1M1 = 1 0 1 0 0 0 0 0 *** 1. [PCF8574 I2C LCD1602 驱动](https://gitee.com/dulht/stc8-exercise/tree/master/I2c%20Lcd1602) ### [硬件I2C驱动](https://gitee.com/dulht/stc8-exercise/blob/master/I2c%20Lcd1602/hardiic.h) #### 新注意点: ``` #define EAXFR 0x80 //I2C功能寄存器为扩展 SFR,逻辑地址位于 XDATA 区域,访问前需要将 P_SW2(BAH)寄存器的最高位(EAXFR)置 1 ``` 初始化中需要 初始化相应针脚,stc8中有4组硬件IIC,需要选择 ``` void hardiic_init(uchar num) { uchar temp = 0x00; switch (num) { case 1: P1M0 = 0x00; P1M1 = 0x00; temp |= 0x00; //0000 0000 I2C_S0=0 I2C_S1=0 (P1.5/SCL, P1.4/SDA) break; case 2: //stc8g没有 P2M0 = 0x00; P2M1 = 0x00; temp |= 0x20; //0010 0000 I2C_S0=1 I2C_S1=0 (P2.5/SCL, P2.4/SDA) break; case 3: //stc8g没有 P7M0 = 0x00; P7M1 = 0x00; temp |= 0x10; //0001 0000 I2C_S0=0 I2C_S1=1(P7.7/SCL, P7.6/SDA) break; case 4: P3M0 = 0x00; P3M1 = 0x00; temp |= 0x30; //0011 0000 I2C_S0=1 I2C_S1=1 (P3.2/SCL, P3.3/SDA) break; } temp |= EAXFR; P_SW2 = temp; I2CCFG = 0xe0; //使能IIC主机模式 I2CMSST = 0x00; //IIC主机状态寄存器清零 } ``` #### 其他部分可直接参考 #### STC-ISP(V6.88i)中[“范例程序”](https://gitee.com/dulht/stc8-exercise/blob/master/I2c%20Lcd1602/hardiic.h) [LCD1602驱动](https://gitee.com/dulht/stc8-exercise/blob/master/I2c%20Lcd1602/i2c.c) ``` //基本写命令 void LCDWriteData(uchar dat) { Start(); //发送起始命令 SendData(ADDR); //发送设备地址+写命令 RecvACK(); //等待完成 SendData(dat); //发送命令 RecvACK(); //等待完成 Stop(); //结束 } void lcd_write_com(uchar com) //写命令函数 { uchar com1, com2; com1 = com | 0x0f; LCDWriteData(com1 & 0xfc); delay2ms(); LCDWriteData(com1 & 0xf8); com2 = com << 4; com2 = com2 | 0x0f; LCDWriteData(com2 & 0xfc); delay2ms(); LCDWriteData(com2 & 0xf8); } void lcd_write_date(uchar date) //写数据函数 { uchar date1, date2; date1 = date | 0x0f; LCDWriteData(date1 & 0xfd); delay2ms(); LCDWriteData(date1 & 0xf9); date2 = date << 4; date2 = date2 | 0x0f; LCDWriteData(date2 & 0xfd); delay2ms(); LCDWriteData(date2 & 0xf9); } ``` #### 初始化 ``` void lcd_init() { lcd_write_com(0x33); //显示模式设置 delay6ms(); lcd_write_com(0x32); //显示模式设置 delay6ms(); lcd_write_com(0x28); //4位总线,双行显示,显示5×7的点阵字符 delay6ms(); lcd_write_com(0x01); //清屏 delay6ms(); lcd_write_com(0x06); //字符进入模式:屏幕不动,字符后移 delay6ms(); // lcd_write_com(0x0c); //显示开,关光标 lcd_write_com(0x0f); //显示开,开光标,光标闪烁 delay6ms(); } ``` ## lcd1602常用指令 ### 4位线IIC开头必须写入以下命令 #### 33H: 原来1602初始化成4位数据线之前必需先初始化成8位(此时命令发送方式是8位格式,但数据线只需接4位) #### 32H: 然后再改到4位线宽,这样初始化才稳定 #### ①01H:清除DDRAM的所有单元,光标被移动到屏幕左上角。 ②02H:DDRAM所有单元的内容不变,光标移至左上角。 ③输入方式设置(EnterModeSet),这些指令规定了两个方面:一是写入一个DDRAM单元后,地址指针如何改变(加一还是减一);二是屏幕上的内容是否滚动。 04H:写入DDRAM后,地址指针减一,比如第一个字符写入8FH,则下一个字符会写入8EH;屏幕上的内容不滚动。 05H:写入DDRAM后,地址指针减一,同上一种情况;每一个字符写入以后,屏幕上的内容向右滚动一个字符位。 #### 06H:写入DDRAM后,地址指针加一,比如第一个字符写入80H,则下一个字符会写入81H;屏幕上的内容也是不滚动。这应该是最常用的一种显示方式。 07H:写入DDRAM后,地址指针加一,同上一种情况;每一个字符写入以后,屏幕上的内容向左滚动一个字符位。 ④屏幕开关、光标开关、闪烁开关。 08H、09H、0AH、0BH:关闭显示屏,实质上是不把DDRAM中的内容对应显示在屏幕上,对DDRAM的操作还是在进行的,执行这条指令,接着对 DDRAM进行写入,屏幕上没有任何内容,但是接着执行下面的某条指令,就能看到刚才屏幕关闭期间,对DDRAM操作的效 果了。 #### 0cH:打开显示屏,不显示光标,光标所在位置的字符不闪烁。 #### 0dH:打开显示屏,不显示光标,光标所在位置的字符闪烁。 #### 0eH:打开显示屏,显示光标,光标所在位置的字符不闪烁。 #### 0fH:打开显示屏,显示光标,光标所在位置的字符闪烁。 关于光标的位置:光标所在的位置指示了下一个被写入的字符所处的位置,加入在写入下一个字符前没有通过指令设置DDRAM的地址,那么这个字符就应该显示在光标指定的地方。 ⑤设置光标移动(本质就是AC的增加还是减少)、整体画面是否滚动。 10H:每输入一次该指令,AC就减一,对应了光标向左移动一格。整体的画面不滚动。 14H:每输入一次该指令,AC就加一,对应了光标向右移动一格。整体的画面不滚动。 18H:每输入一次该指令,整体的画面就向左滚动一个字符位。 1CH:每输入一次该指令,整体的画面就向右滚动一个字符位。画面在滚动的时候,每行的首尾是连在一起的,也就是每行的第一个字符,若左移25次,就会显示在该行的最后一格。在画面滚动的过程中,AC的值也是变化的。 #### ⑥显示模式设定指令,设定了显示几行,显示什么样的点阵字符,数据总线占用几位。 20H:4位总线,单行显示,显示5×7的点阵字符。 24H:4位总线,单行显示,显示5×10的点阵字符。 #### 28H:4位总线,双行显示,显示5×7的点阵字符。 2CH:4位总线,双行显示,显示5×10的点阵字符。 30H:8位总线,单行显示,显示5×7的点阵字符。 34H:8位总线,单行显示,显示5×10的点阵字符。 38H:8位总线,双行显示,显示5×7的点阵字符。这是最常用的一种模式。3CH:8位总线,双行显示,显示5×10的点阵字符。 **推荐** ``` void lcd_init() { lcd_write_com(0x33); //原来1602初始化成4位数据线之前必需先初始化成8位(此时命令发送方式是8位格式,但数据线只需接4位) delay6ms(); lcd_write_com(0x32); //然后再改到4位线宽,这样初始化才稳定 delay6ms(); lcd_write_com(0x28); //4位总线,双行显示,显示5×7的点阵字符 delay6ms(); lcd_write_com(0x01); //清屏 delay6ms(); lcd_write_com(0x06); //字符进入模式:屏幕不动,字符后移 delay6ms(); // lcd_write_com(0x0c); //显示开,关光标 lcd_write_com(0x0f); //显示开,开光标,光标闪烁 delay6ms(); } ``` 2. [nrf24l01 spi 驱动](https://gitee.com/dulht/stc8-exercise/blob/master/projects/%E7%BB%BC%E5%90%88%E9%A1%B9%E7%9B%AE/nrf24l01.h) 除IO口需要设置其他不用改动 3.