[活动专区]

【赛元95F】自制SC95F8617测试板及测试程序

[复制链接]
2617|3
手机看帖
扫描二维码
随时随地手机跟帖
crazyfool|  楼主 | 2020-4-5 22:15 | 显示全部楼层 |阅读模式
本帖最后由 crazyfool 于 2020-4-5 22:52 编辑
//************************************************************
//  Copyright (c) 深圳市赛元微电子有限公司
//        文件名称        : main.c
//        作者                :
//        模块功能        : LCD 显示code
//        局部函数列表:
//  最后更正日期:
//         版本                : V1.0
//         更改记录        : rom前256byte禁止查表,因此在编译的时候,设置keil->option for Target->BL51 Locate->Code Range:0x100
//*************************************************************

#include "LCD_INIT.h"

/*
本测试电路使用的LCD与MCU的连接是:
COM1                C4                P34
COM2                C5                P35
COM3                C6                P36
COM4                C7                P37
SEG1                S0                P33
SEG2                S1                P32
SEG3                S2                P31
SEG4                S3                P30
SEG5                S4                P10
SEG6                S6                P12
SEG7                S8                P14
SEG8                S9                P15
可见,硬件上,COM注意要么接在COM0-COM3要么接在COM4-COM7,但SEG口随意
根据上述接线,要配置对应IO口为LCD输出
下面寄存器
DDRCON
OTCON
要根据LCD的实际参数而配置

** LCD规格:1/4 duty 1/3bias 3.3V

*/
void LCD_Init(void)         //DDIC配置为LCD,显示函数和配置需根据LCD屏进行修改
{
        DDRCON = 0xB0;    //-xyy zzzz  x:LCD/LED模式 y:占空比  z:LCD电压调节
        P0VO = 0x00;
        P1VO = 0x35;
        P2VO = 0x00;
        P3VO = 0xFF;
        OTCON = 0x04;    //---- xxyz  x:LCD分压电阻 y:复位管脚选择 z:LCD偏置电压
        
}
//************************************************************
//  Copyright (c) 深圳市赛元微电子有限公司
//        文件名称        : LCD_DISPLAY.c
//        作者                :
//        模块功能        : LCD 显示
//        局部函数列表:
//  最后更正日期:
//         版本                : V1.0
//         更改记录        : rom前256byte禁止查表,因此在编译的时候,设置keil->option for Target->BL51 Locate->Code Range:0x100
//*************************************************************
#include "lcd_display.h"

static        unsigned char xdata        Display_Mode = 0;//0时钟 1NTC温度 2电压值 3DS18B20温度

//-----------------------LCD编码表---------------------------
static        unsigned char code LcdCodeTab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00,0xff};
//-----------------------编码表下标数据-----------------------
static        unsigned char xdata        LcdDataTab[4] = {0,0,0,0};//即LCD待显示的数字
//-----------------------LCD显示RAM配置-----------------------
static        unsigned char xdata LcdDisplay[28] _at_  0x1000;        //注意:不同LCD的RAM起始地址不同
//-----------------------数据各位缓存变量

static        unsigned char xdata        SEGA,SEGB,SEGC,SEGD,SEGE,SEGF,SEGG,SEGDP;//8个段不是有规律分配,需要处理

/**************************************************
*函数名称:void LcdSegData(unsigned char LcData,LcdSelCOM COMx)
*函数功能:LCD显示数据转换
*入口参数:LcdData               LCD显示数据
                   COMx                             COM口选择(取值范围:LCDCOM0~7)
*出口参数:void
*功能说明:LcdDisplay[]数组下标值必须根据所选择的SEG口对应

**特别解读:程序中的COMx == LCDCOM0 等仅仅表示要写第几个位
  并将数据写入对应的RAM区,仅仅是为了确定RAM地址

** LCD规格:1/4 duty 1/3bias 3.3V
**************************************************/

static void LcdSegData(unsigned char LcdData,LcdSelCOM COMx)
{
        switch(Display_Mode)
        {
                case        0://时钟
                if(COMx == LCDCOM0)
                {
                        LcdData |= 0x80;//显示冒号
                }
                break;
               
                case        1://NTC
                if(COMx == LCDCOM0)
                {
                        LcdData = 0;//不显示
                }                        
                if(COMx == LCDCOM1)
                {
                        LcdData = 0;//不显示
                }        
                break;
               
                case        2://电压值
                if(COMx == LCDCOM0)
                {
                        LcdData = 0;//不显示
                }               
                if(COMx == LCDCOM2)
                {
                        LcdData |= 0x80;//显示小数点
                }        
                break;
               
                case        3://DS18B20温度
                if(COMx == LCDCOM0)
                {
                        LcdData = 0;//不显示
                }                        
                if(COMx == LCDCOM1)
                {
                        LcdData = 0;//不显示
                }               
                break;
               
                default:break;
               
        }
        //如下四段,连在一个SEG
        SEGA  = ((LcdData >> 0) & 0X01) << 4;
        SEGF  = ((LcdData >> 5) & 0X01) << 5;
        SEGE  = ((LcdData >> 4) & 0X01) << 6;
        SEGDP = ((LcdData >> 7) & 0X01) << 7;
        
        //如下四段,连在一个SEG
        SEGB  = ((LcdData >> 1) & 0X01) << 4;
        SEGG  = ((LcdData >> 6) & 0X01) << 5;
        SEGC  = ((LcdData >> 2) & 0X01) << 6;
        SEGD  = ((LcdData >> 3) & 0X01) << 7;

        //发送第0个字符对应的显示RAM区
        if(COMx == LCDCOM0)
        {
                LcdDisplay[0]  =  (0x00 |SEGA | SEGF | SEGE | SEGDP);
                LcdDisplay[1]  =  (0x00 |SEGB | SEGG | SEGC | SEGD);
               
        }
        
        //发送第1个字符对应的显示RAM区
        if(COMx == LCDCOM1)
        {
                LcdDisplay[2]  =  (0x00 |SEGA | SEGF | SEGE | SEGDP);
                LcdDisplay[3]  =  (0x00 |SEGB | SEGG | SEGC | SEGD);        
        }
        
        //发送第2个字符对应的显示RAM区
        if(COMx == LCDCOM2)
        {
                LcdDisplay[4]  =  (0x00 |SEGA | SEGF | SEGE | SEGDP);
                LcdDisplay[6]  =  (0x00 |SEGB | SEGG | SEGC | SEGD);        
        }
        
        //发送第3个字符对应的显示RAM区
        if(COMx == LCDCOM3)
        {
                LcdDisplay[8]  =  (0x00 |SEGA | SEGF | SEGE | SEGDP);
                LcdDisplay[9]  =  (0x00 |SEGB | SEGG | SEGC | SEGD);        
        }

}

/**************************************************
*函数名称:void LcdDisplay(void)
*函数功能:LCD显示
*入口参数:无
*出口参数:void
*功能说明:COM口必须跟使用的COM相对应
**************************************************/
void Lcd_Display(void)
{
        switch(Display_Mode)
        {
                case        0://RTC 注意SEG1的P1段要点亮
                LcdDataTab[0] = DS1302_Tab[2] >> 4;//时
                LcdDataTab[1] = DS1302_Tab[2] & 0x0f;
                LcdDataTab[2] = DS1302_Tab[1] >> 4;//分
                LcdDataTab[3] = DS1302_Tab[1] & 0x0f;
                break;
               
                case         1://NTC温度
                LcdDataTab[0] = 0;
                LcdDataTab[1] = 0;
                LcdDataTab[2] = NTC_Val / 10;
                LcdDataTab[3] = NTC_Val % 10;        
                break;
               
                case        2://电压值
                LcdDataTab[0] = 0;
                LcdDataTab[1] = Voltage_Val / 100;
                LcdDataTab[2] = Voltage_Val % 100 / 10;
                LcdDataTab[3] = Voltage_Val % 10;        
                break;
               
                case        3://DS18B20温度值
                LcdDataTab[0] = 0;
                LcdDataTab[1] = 0;
                LcdDataTab[2] = DS18B20_Val / 10;
                LcdDataTab[3] = DS18B20_Val % 10;        
                break;
               
                default:
                Display_Mode = 0;        
                break;
               
        }
        LcdSegData(LcdCodeTab[LcdDataTab[0]],LCDCOM0);//发送第0个字符对应的RAM
        LcdSegData(LcdCodeTab[LcdDataTab[1]],LCDCOM1);//发送第1个字符对应的RAM
        LcdSegData(LcdCodeTab[LcdDataTab[2]],LCDCOM2);//发送第2个字符对应的RAM
        LcdSegData(LcdCodeTab[LcdDataTab[3]],LCDCOM3);//发送第3个字符对应的RAM
}

/**************************************************
*函数名称:void        Dis_Mode_Handle(void)
*函数功能:LCD显示模式处理
*入口参数:无
*出口参数:void
*功能说明:通过TK24实现改变显示模式
**************************************************/
void        Dis_Mode_Handle(void)
{
        Display_Mode ++;
        if(Display_Mode > 3)
        {
                Display_Mode = 0;
        }
}
#include "TK_Handle.H"

/*
特别说明:原理图设计时,标注有误
电路板上的TK27对应真实TK24 TK26对应真实TK25
短按分别选择显示内容 RGB颜色码
长按TK25改变占空比
*/
#define                        TK24                0x01000000                //TK24用以改变LCD显示模式【变量定义在LCD_DISPLAY.C中】
#define                        TK25                0x02000000                //TK25用以切换RGB色

static                unsigned long        xdata        exKeyValueFlag = 0;                //当前轮按键标志
static                unsigned char xdata        KeyValid_Flag = 0;                //按键有效标志,蜂鸣器响0.1s
static                unsigned char xdata        RGB_Code = 1;                                        //RGB颜色码,0-7对应不同颜色
static                unsigned char xdata        PWM_Dudy = 2;                                        //PWM占空比,步长为2%,为避免太刺眼,限制在20%


/*****************************************************
*函数名称:void        TK_Init(void)
*函数功能:触摸按键初始化 - 调用库函数
*入口参数:void
*出口参数:void
** 再封装,此为第一步,在系统初始化时调用
** 注意初始化持续几百毫秒,建议先于定时器 WDT等前初始化
*****************************************************/
void        TK_Init(void)//触控按键初始化
{
        TouchKeyInit();
}

/**************************************************
*函数名称:void  TK_Scan(void)
*函数功能:扫描TK和显示
*入口参数:void
*出口参数:void  
** 每10ms调用一次
**************************************************/
void TK_Scan(void)
{                                      
        if(SOCAPI_TouchKeyStatus&0x80)            //重要步骤2:触摸键扫描一轮标志,是否调用TouchKeyScan()一定要根据此标志位置起后
        {                                                                                                                                                        
                SOCAPI_TouchKeyStatus &= 0x7f;        //重要步骤3: 清除标志位, 需要外部清除。                                                                                                            
                exKeyValueFlag = TouchKeyScan();//按键数据处理函数   
                TouchKeyRestart();                                //启动下一轮转换                                                                                                                                                                                                                                                                        
        }                             
}

/**************************************************
*函数名称:void  TK_Handle(void)
*函数功能:TK按键处理函数
*入口参数:void
*出口参数:void  
** 每10ms调用一次,建议紧随在TK_Scan函数之后
**************************************************/
void TK_Handle(void)
{   
        static        bit                TK24_Flag = 0,TK25_Flag = 0;//按键标志,只响应短按
        static        unsigned int xdata        Time_Cnt = 0;//长按标志,0.3s有效
        
        if((exKeyValueFlag & TK24) == TK24)        
        {               
                if(TK24_Flag == 0)
                {
                        TK24_Flag = 1;
                        KeyValid_Flag = 1;        
                        Dis_Mode_Handle();
                }                                                                                                                                                                                                                                                                 
        }
        else
        {
                TK24_Flag = 0;
        }
        
        if((exKeyValueFlag & TK25) == TK25)        
        {               
                if(TK25_Flag == 0)
                {
                        TK25_Flag = 1;
                        Time_Cnt = 0;
                        KeyValid_Flag = 1;        
                        RGB_Code ++;
                        if(RGB_Code > 7)
                        {
                                RGB_Code = 1;
                        }
                }               
                else if( ++Time_Cnt >= 30)
                {
                        Time_Cnt = 0;
                        PWM_Dudy += 2;
                        if(PWM_Dudy > 20)
                        {
                                PWM_Dudy = 2;
                        }
                }
        }
        else
        {
                TK25_Flag = 0;
                Time_Cnt = 0;
        }
}

/**************************************************
*函数名称:void  Buzzer_Handle(void)
*函数功能:蜂鸣器响0.1s
*入口参数:void
*出口参数:void  
** 每20ms调用一次
**************************************************/
void  Buzzer_Handle(void)
{
        static        unsigned char xdata        Time_Cnt = 0;
        
        if(KeyValid_Flag > 0)
        {
                Buzzer_Switch(1);
                Time_Cnt ++;
                if(Time_Cnt > 5)
                {
                        Time_Cnt = 0;
                        Buzzer_Switch(0);
                        KeyValid_Flag = 0;
                }
        }
}

/**************************************************
*函数名称:void  RGB_Handle(void)
*函数功能:RGB显示函数,这里只显示颜色,未改变占空比【固定】
*入口参数:void
*出口参数:void  
** 每20ms调用一次
extern void        RGB_R_Switch(unsigned int Duty_Val);
extern void        RGB_G_Switch(unsigned int Duty_Val);
extern void        RGB_B_Switch(unsigned int Duty_Val);
**************************************************/
void  RGB_Handle(void)
{
        switch(RGB_Code)
        {
                case        0:
                RGB_R_Switch(0);
                RGB_G_Switch(0);
                RGB_B_Switch(0);               
                break;
               
                case        1:
                RGB_R_Switch(PWM_Dudy);
                RGB_G_Switch(0);
                RGB_B_Switch(0);               
                break;
               
                case        2:
                RGB_R_Switch(0);
                RGB_G_Switch(PWM_Dudy);
                RGB_B_Switch(0);               
                break;
               
                case        3:
                RGB_R_Switch(0);
                RGB_G_Switch(0);
                RGB_B_Switch(PWM_Dudy);               
                break;
               
                case        4:
                RGB_R_Switch(PWM_Dudy);
                RGB_G_Switch(PWM_Dudy);
                RGB_B_Switch(0);               
                break;
               
                case        5:
                RGB_R_Switch(PWM_Dudy);
                RGB_G_Switch(0);
                RGB_B_Switch(PWM_Dudy);               
                break;
               
                case        6:
                RGB_R_Switch(0);
                RGB_G_Switch(PWM_Dudy);
                RGB_B_Switch(PWM_Dudy);               
                break;
               
                case        7:
                RGB_R_Switch(PWM_Dudy);
                RGB_G_Switch(PWM_Dudy);
                RGB_B_Switch(PWM_Dudy);               
                break;
               
                default:break;
        }
        
}


一、板载资源
1.电位器 - AIN3(与2实现多通道切换)测试ADC功能
2.NTC - AIN2 (与1实现多通道切换)实现廉价测温,使用乘除法器实现数据计算。这里只简单查表0-40°温度。
3.无源蜂鸣器 - PWM40 测试PWM
4.4个LED灯 - PWM50 - PWM53,可测试PWM、可作为TK指示灯
5.RGB灯珠(5050) - PWM41 -PWM42 ,测试PWM,颜色选择、占空比调节(测试TK长按功能)
6.DS18B20 - 单总线数字温度传感器,时序要求严格,测试定时器、IO口方向动态改变(输入输出快速切换),并与NTC测温做比较
7.4路TK - TK24 - TK27,这是重点之一,熟悉TK调试使用基本流程。
8.DS1302 - RTC,测试LCD,并用UART0实现RTC调整(带后备电池,可断电运行)
9.LCD - 4COM,8SEG,1/4占空比,1/3偏压,3.3V  测试硬件LCD功能。这是重点之二。

二、个人遇到的几个坑
1.PWM的占空比设定值注意不能超过PWM周期,假设周期为2000个数,则占空比应在0-2000之间设定;本人一开始,以12位PWM对应范围0-4095进行设置,以致无法实现预期的占空比调节。
2.TK设计时,对新手或不熟悉的用户来说,应充分阅读学习设计指南。比如走线、线距、敷铜等操作。
3.赛元单片机的GPIO有三种模式(推挽输出、高阻输入(上电默认)、上拉输入),无开漏输出(可程序实现),也不具备准双向功能,当某个IO口同时要作为输入输出时,应注意根据需要改变方向设置。
4.未用IO或封装未引出IO,都要设为推挽输出。
5.TK功能的IO要设为推挽输出,并且直接输出1。
6.使用T1作为串口0的波特率,注意不能启动T1,即TR1不能设为1。
7.官方给的8617Demo程序,定时器初始化部分,应该有误,此型号HRC为32MHz,不是16MHz
8.LCD在硬件设计时,对4COM的LCD而言,COM口只能分配在COM0 - COM3 或 COM4 - COM7,不能随意分配,但分配好COM之余,SEG则可以根据布局需要,随意分配,只需注意对应的型号的单片机的RAM区起始地址。然后根据LCD手册对应段所在位置(接在哪个SEG上,适当处理后,往对应的RAM地址丢数据即可;但这里要注意,如果COM接在COM0-COM3则对应RAM的低4位有效,若是接在COM4-COM7,则是对应RAM的高4位有效。

三、致谢
1.此硬件为第1版,期间多次请教网友、赛元技术支持、康力佳FAE,再次深表感谢!本人能力有限,未能全部领悟,请多包涵。
2.欢迎交流,请勿喷——我这个中年男子。




程序截图.jpg
实物图.jpg

SC95F8617实验板电路图.pdf

77.71 KB

实验效果短视频.rar

1.56 MB

使用特权

评论回复

相关帖子

lisingch| | 2020-4-5 23:20 | 显示全部楼层
板子看着挺漂亮!板子上再加一片EEPROM和SPI FLASH,IO通过排针引出方便其它硬件实验。

使用特权

评论回复
21ic小喇叭| | 2020-4-7 15:05 | 显示全部楼层
感谢分享,奖励您50家园币,家园币可以兑换礼品或抽奖,欢迎体验~

使用特权

评论回复
crazyfool|  楼主 | 2020-4-7 16:23 | 显示全部楼层
lisingch 发表于 2020-4-5 23:20
板子看着挺漂亮!板子上再加一片EEPROM和SPI FLASH,IO通过排针引出方便其它硬件实验。 ...

谢谢鼓励!板子其实挺渣的,我一般没画板
一般应用从成本考虑,估计不会外挂EEPROM了( 而直接使用内部EEPROM),至于Flash视情况而定。
这个板尺寸小了(或不合适),TK焊盘也不符合指南要求的12-14mm的尺寸。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

96

主题

172

帖子

2

粉丝