woshixy1 发表于 2025-2-9 00:29:10

用擎天柱开发板做了一个lcd1602 4线驱动

<p>开头还是那句话</p>
<p><strong>哪怕梦想让我们拼的遍体鳞伤!这一次我们也要勇往直前!</strong></p>
<p>想做一个小装置 先做第一步显示模块</p>
<p><img src="data/attachment/forum/202502/09/001839z450v8ku957hhjr5.png" alt="微信截图_20250209001343.png" title="微信截图_20250209001343.png" /></p>
<p>没放P3那个上拉电阻 p3和s8050之间也没加限流电阻 。</p>
<p>R11 随便找了一个 电位器</p>
<p>A和vcc加了一个限流电阻 也不知道有没有必要。</p>
<p>因为不知道 lcd1602里面有没有集成限流电阻 所以我自己就加了一个 不过看别人都没加。。。</p>
<p>vcc和gnd之间没有加电容</p>
<p>还发现一个问题 整套系统连接 电脑usb口供电可以正常运行 但是单独连接手机的充电头就行不。。不知道为啥</p>
<p>还有个问题 单片机不能 自动下载 每次都要在电脑上点了下载之后 在按P32 在按重启 才能下载成功。。。</p>
<p>视频效果</p>
<video controls="controls" src="forum.php?mod=attachment&amp;aid=83927"></video>
<p>代码如下</p>
<pre><code>#include &quot;ai8051u.h&quot;
#include &quot;stc32_stc8_usb.h&quot;
#include &quot;intrins.h&quot;

char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = &quot;@STCISP#&quot;;



sbit LCD1602_EN=P0^4;
sbit LCD1602_RS=P0^5;
sbit LCD1602_K=P0^6;

sbit LCDdata4 =P0^3;
sbit LCDdata3 =P0^2;
sbit LCDdata2 =P0^1;
sbit LCDdata1 =P0^0;

void LCD1602_WriteCmd(u8 cmd_data);//写入命令数据
void LCD1602_WriteData(u8 cmd_data);//写入显示用数据
void LCD1602_init(void);//初始化
void LCD1602_clear(void);//清屏指令 清除之前缓存的数据
void LCD1602_show_string(u8 x,u8 y,u8 *str);//x=0-15,y=0-1,str 是字符串变量

void Delay1ms(void);        //@24.000MHz
void Delay500ms(void);        //@24.000MHz

void main(void)
{
                WTST =0;//设置程序指令延时参数
                EAXFR =1;//扩展寄存器(XFR)访问使能
                CKCON=0;//提高访问XRAM速度

          P0M1 = 0x00;   P0M0 = 0x00;   //设置为推双向口
    P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
    P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
    P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
    P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
    P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
    P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
    P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口

                usb_init();
                IE2 = 0x80;        //sub允许中断
                EA = 1; //总中断
                while (DeviceState != DEVSTATE_CONFIGURED);   //等待USB完成配置



        while(1)
{
        LCD1602_init();//初始化
        LCD1602_show_string(0,0,&quot;stcaimcu&quot;);//x=0-15,y=0-1,str 是字符串变量
        LCD1602_show_string(0,1,&quot;AI8051U&quot;);//x=0-15,y=0-1,str 是字符串变量

        LCD1602_K = 0;
        Delay500ms();
        LCD1602_K = 1;
        Delay500ms();






//                          if (bUsbOutReady)
//      {
//          //USB_SendData(UsbOutBuffer,OutNumber);   //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
//   
//                                        printf(&quot;stc 真的很棒 \r\n&quot;);
//   
//                                        usb_OUT_done();
//      }
//


        }




}


void Delay1ms(void)        //@24.000MHz
{
        unsigned long edata i;

        _nop_();
        _nop_();
        _nop_();
        i = 5998UL;
        while (i) i--;
}


void Delay500ms(void)        //@24.000MHz
{
        unsigned char data i, j, k;

        _nop_();
        _nop_();
        i = 61;
        j = 225;
        k = 62;
        do
        {
                do
                {
                        while (--k);
                } while (--j);
        } while (--i);
}



void LCD1602_WriteCmd(u8 cmd_data)//写入命令数据
{
        u8 i;
        LCD1602_RS=0;//命令模式
        LCD1602_EN=0;//使能管脚
        for(i=2;i&gt;0;i--)
        {
                LCDdata4 = cmd_data &amp; 0x80;
                LCDdata3 = cmd_data &amp; 0x40;
                LCDdata2 = cmd_data &amp; 0x20;
                LCDdata1 = cmd_data &amp; 0x10;

                LCD1602_EN=1;//上升沿发射数据
                Delay1ms();
                LCD1602_EN=0;//产生下降沿
                Delay1ms();

                cmd_data = cmd_data &lt;&lt; 4;
        }

}


void LCD1602_WriteData(u8 cmd_data)//写入显示用数据
{
        u8 i;
        LCD1602_RS=1;//数据模式
        LCD1602_EN=0;//使能管脚
        for(i=2;i&gt;0;i--)
        {
                LCDdata4 = cmd_data &amp; 0x80;
                LCDdata3 = cmd_data &amp; 0x40;
                LCDdata2 = cmd_data &amp; 0x20;
                LCDdata1 = cmd_data &amp; 0x10;

                LCD1602_EN=1;//上升沿发射数据
                Delay1ms();
                LCD1602_EN=0;//产生下降沿
                Delay1ms();

                cmd_data = cmd_data &lt;&lt; 4;
        }

}


void LCD1602_init(void)//初始化
{
        LCD1602_WriteCmd(0x28);//功能设定 8位数据总线 显示两行 5*7点阵
        LCD1602_WriteCmd(0x0c);//开启显示 不显示光标 光标闪烁
        LCD1602_WriteCmd(0x06);//模式设置 光标后移 屏幕不动
        LCD1602_WriteCmd(0x01);//清屏指令 清除之前缓存的数据
}

void LCD1602_clear(void)//清屏指令 清除之前缓存的数据
{
        LCD1602_WriteCmd(0x01);
}




void LCD1602_show_string(u8 x,u8 y,u8 *str)//x=0-15,y=0-1,str 是字符串变量
{
        u8 i=0;
        if(x&gt;15|y&gt;2) return;//超出显示范围
        if(y&lt;1)//第一行
        {

                while(*str!='\0')
                {
                        if(i+x&lt;16)//判断是字符串是否再第一行显示
                        {
                                LCD1602_WriteCmd(0x00+0x80+x+i);//写入第一行显示字符的位置命令
                                //0x00 就是第一行的起始偏移值 当然可以不写
                                //因为显示的DDRAM地址第一行是 00到0F
                        }
                        else
                        {
                                LCD1602_WriteCmd(0x40+0x80+x+i-16);//写入第二行显示字符的位置命令
                                //减去16就是 减去上一行的字符数
                        }
                        LCD1602_WriteData(*str);//指针取出 这个位置字符串对应的 字符
                        str++;
                        i++;
                }
        }
        else//直接在第二行显示数据的情况
        {
                while(*str!='\0')
                {
                        if(i+x&lt;16)//判断是字符串是否再一行显示
                        {
                                LCD1602_WriteCmd(0x40+0x80+x+i);//写入第二行显示字符的位置命令
                        }
                        else
                        {
                                LCD1602_WriteCmd(0x00+0x80+x+i-16);//写入第一行显示字符的位置命令
                                //减去16就是 减去上一行的字符数 也就是第二行的字符数
                        }
                        LCD1602_WriteData(*str);//指针取出 这个位置字符串对应的 字符
                        str++;
                        i++;       
                }
        }
}



</code></pre>

DebugLab 发表于 2025-2-9 13:52:07

P3是一组并口(8位),建议写成如P32
IO直接接NPN三极管,要打开内部4K上拉电阻并设置为开漏,不能设置成推挽,否则可能烧毁IO

tianjing818 发表于 2025-2-9 14:52:25

{:qiang:}

zhaoye818 发表于 2025-2-9 14:54:09

必须点赞

woshixy1 发表于 2025-2-9 19:28:25

DebugLab 发表于 2025-2-9 13:52
P3是一组并口(8位),建议写成如P32
IO直接接NPN三极管,要打开内部4K上拉电阻并设置为开漏,不能设置成推 ...

好嘞 以后弄图更精确一些
我给io都设置成了 准双向了 以后还是给 B极和io之间加个电阻 不用必须是上拉电阻吧?直接用用内部的上拉也可以是吧

我不是很明白这个电阻

是给io设置成准双向 放一个限流电阻
还是给io设置成开漏 用单片机io口内部的上拉电阻

这两种那个好呢?为啥

angmall 发表于 2025-2-9 20:03:57

还发现一个问题 整套系统连接 电脑usb口供电可以正常运行 但是单独连接手机的充电头就行不。。不知道为啥
主要是卡在USB初始化部分的死循环了,把代码修改以下就好

long int i = 10000000L;



    while(DeviceState != (DEVSTATE_CONFIGURED))   //等待USB完成配置
    {
            if((--i)==0)
                  break;

    }       

DebugLab 发表于 2025-2-10 00:10:54

woshixy1 发表于 2025-2-9 19:28
好嘞 以后弄图更精确一些
我给io都设置成了 准双向了 以后还是给 B极和io之间加个电阻 不用必须是上拉电 ...

开漏+内部上拉,可以省掉外部上拉电阻

woshixy1 发表于 2025-2-10 05:04:44

DebugLab 发表于 2025-2-10 00:10
开漏+内部上拉,可以省掉外部上拉电阻

谢谢

woshixy1 发表于 2025-2-10 05:05:10

angmall 发表于 2025-2-9 20:03
主要是卡在USB初始化部分的死循环了,把代码修改以下就好

long int i = 10000000L;


谢谢

Ayb_ice 发表于 2025-2-10 08:27:38

时序延时太长了
页: [1] 2
查看完整版本: 用擎天柱开发板做了一个lcd1602 4线驱动