📄 lcdc_040.c
字号:
Clock tolerance df :
A: df < min(Phase_Seg1, Phase_Seg2) / (2 * (13*bit_time - Phase_Seg2))
B: df < SJW / (20 * bit_time)
A: df < 2/(2*(13*11-3)) = 1/(141-3) = 1/138 = 0.7246%
B: df < 2/(20*11) = 1/110 = 0.9091%
Actual clock tolerance is 0.7246% - 0.5381% = 0.1865% (no problem for quartz)
*/
SFRPAGE = CAN0_PAGE;
CAN0CN |= 0x41; // Configuration Change Enable CCE and INIT
CAN0ADR = BITREG ; // Point to Bit Timing register
CAN0DAT = 0x2640; // see above
CAN0ADR = IF1CMDMSK; // Point to Command Mask 1
CAN0DAT = 0x0087; // Config for TX : WRITE to CAN RAM, write data bytes,
// set TXrqst/NewDat, clr IntPnd
// RX-IF2 operation may interrupt TX-IF1 operation
CAN0ADR = IF2CMDMSK; // Point to Command Mask 2
CAN0DATL = 0x1F; // Config for RX : READ CAN RAM, read data bytes,
// clr NewDat and IntPnd
CAN0CN |= 0x06; // Global Int. Enable IE and SIE
CAN0CN &= ~0x41; // Clear CCE and INIT bits, starts CAN state machine
}
/*
void transmit(char MsgNum)
{
uchar num;
SFRPAGE=CAN0_PAGE;
CAN0ADR=IF1CMDMSK;
CAN0DAT=0x0087;
CAN0ADR=IF1DATA1;
for(num=0;num<8;num++)
{CAN0DATH=sdata[num];
num++;
CAN0DATL=sdata[num];
}
CAN0ADR=IF1CMDRQST;
CAN0DATL=MsgNum;
}
void receive_data(uchar MsgNum)
{
uchar i;
SFRPAGE=CAN0_PAGE;
CAN0ADR=IF2CMDMSK;
CAN0DATL=0x0f;
CAN0ADR=IF2CMDRQST;
CAN0DATL=MsgNum;
CAN0ADR=IF2DATA1;
for(i=0;i<8;i++)
{rdata[i]=CAN0DATL;
i++;
rdata[i]=CAN0DATH;
}
isnewdata=1;
}
*/
void transmit(char MsgNum,char *p,char len)
{
char i;
SFRPAGE=CAN0_PAGE;
CAN0ADR=IF1CMDMSK;
CAN0DAT=0x0087;
CAN0ADR=IF1DATA1;
for(i=0;i<len;i+=2)
{CAN0DATH=*p++;
CAN0DATL=*p++;
}
CAN0ADR=IF1CMDRQST;
CAN0DATL=MsgNum;
}
void receive_data(uchar MsgNum,char *p,char len)
{
char i;
SFRPAGE=CAN0_PAGE;
CAN0ADR=IF2CMDMSK;
CAN0DATL=0x0f;
CAN0ADR=IF2CMDRQST;
CAN0DATL=MsgNum;
CAN0ADR=IF2DATA1;
for(i=0;i<len;i+=2)
{*p++=CAN0DATH;
*p++=CAN0DATL;
}
isnewdata=1;
}
////////////////////////////////////////////////////////////////////////////////
//Interrupt Service Routine
////////////////////////////////////////////////////////////////////////////////
void ISRname (void) interrupt 19
{
temppage=SFRPAGE;
SFRPAGE=CAN0_PAGE;
status = CAN0STA;
if ((status&0x10) != 0)
{ // RxOk is set, interrupt caused by reception
CAN0STA &=0xef; // Reset RxOk, set LEC to NoChange
/* read message number from CAN INTREG */
receive_data (0x04,rdata,8); // Up to now, we have only one RX message
lcdtoken=1;
}
SFRPAGE=temppage;
}
void spi_init()
{
SFRPAGE = SPI0_PAGE;
SPI0CFG = 0x40;
SPI0CN = 0x01;
SPI0CKR = 0x6D;
}
void delay1us(void)
{
uchar xdata i;
for(i=10;i>0;i--);
}
void writelcd(uchar spi_data) //向LV595写数据以SPI方式
{
uint xdata i,j,k;
for(i=0;i<9;i++);
LcdCs=0;
delay1us();
SPI_BUSY=1;
SFRPAGE = SPI0_PAGE;
SPI0DAT=spi_data;
for(j=0;j<500;j++)
{
if(!SPI_BUSY)break;
}
delay1us();
LcdCs=1;
delay1us();
delay1us();
delay1us();
delay1us();
delay1us();
delay1us();
for(k=0;k<5000;k++);
/* **************************************************************************
// 以下这段代码,是用IO口模拟SPI传输的程序
LcdCs=0;
for(i=0;i<8;i++)
{ SPICLK=0;
if(spi_data&0x80)
spi_mosi=1;
else
spi_mosi=0;
spi_data<<=1;
SPICLK=1;
for(j=0;j<10;j++)
{_nop_();}
SPICLK=0;
}
LcdCs=1;
/***************************************************************************/
}
void writecode(uchar ins) //向液晶控制模块写命令
{
uchar xdata t;
uint xdata j;
for(j=0;j<500;j++);
virt_port|=ins&0xf0; //取高字节向1602写数据
writelcd(virt_port); //先写高4位后再写低4位 这是在选择四个数据线的时候
virt_port|=0x08;
writelcd(virt_port); //使能E脚为高电平
virt_port&=~0x08;
writelcd(virt_port); //使能E脚为低电平
t=ins<<4;
virt_port|=t&0xf0; //取低字节向1602写数据
writelcd(virt_port);
virt_port|=0x08; //使能E脚为高电平
writelcd(virt_port);
virt_port&=~0x08; //使能E脚为低电平
writelcd(virt_port);
virt_port=0;
writelcd(virt_port);
}
void writedata(uchar d) //写数据到1602
{
uchar xdata i,t;
uint xdata j;
for(j=0;j<500;j++);
virt_port|=0x02; //光标返回指令
writelcd(virt_port);
virt_port|=d&0xf0; //取高字节数据给数据寄存器
writelcd(virt_port);
virt_port|=0x08; //使能E脚为高电平
writelcd(virt_port);
virt_port&=0xf7; //使能E脚为低电平
writelcd(virt_port);
virt_port&=0x07; //设置光标右移,文字也右移
writelcd(virt_port);
t=d&0x0f;
virt_port|=t<<4; //取低字节数据给数据寄存器
writelcd(virt_port);
virt_port|=0x08; //使能E脚为高电平
writelcd(virt_port);
for(i=3;i>0;i--);
virt_port&=0xf7; //使能E脚为低电平
writelcd(virt_port);
virt_port=0; //数据清零
writelcd(virt_port);
}
void lcdchar (void)
{
uint xdata i,j,k;
for(j=0;j<5000;j++); //数据读、写操作,画面不动
for(k=0;k<5000;k++);
for(i=0;i<8;i++)
{
writedata(rdata[i]);
for(j=0;j<1000;j++);
for(k=0;k<1000;k++);
for(k=0;k<5000;k++);
for(k=0;k<1000;k++);
for(k=0;k<5000;k++);
for(k=0;k<5000;k++);
for(k=0;k<5000;k++);
}
}
void lcdinit()
{
uint xdata i;
virt_port=0x00;
writelcd(virt_port); //RS脚为零写指令寄存器 RW为低电平
virt_port|=0x08; //使能脚E=1
writelcd(virt_port);
virt_port&=0xf7; //使E=0使能脚发生跳变高--低
writelcd(virt_port);
for(i=1000;i>0;i--); //3次延时,重要!
for(i=8000;i>0;i--); //用延时代替查询
virt_port=0; //写入20码,设置为4位总线方式,非常重要!!!!!
writelcd(virt_port);
virt_port|=0x20; //只写高字节
writelcd(virt_port);
virt_port|=0x08; //E=1
writelcd(virt_port);
for(i=20;i>0;i--); //使命令执行
virt_port&=0xf7; //E=0
writelcd(virt_port);
for(i=10;i>0;i--);
virt_port=0;
writelcd(virt_port);
writecode(0x38); //设两行显示,4线方式5*10字符显示
for(i=50;i>0;i--);
writecode(0x06); //光标右移
for(i=50;i>0;i--);
writecode(0x0c); //开显示指令
for(i=50;i>0;i--);
writecode(0x02); //光标返回指令
for(i=50;i>0;i--);
writecode(0x01); //清屏指令
for(i=50;i>0;i--);
}
void spi_srs () interrupt 6
{
if(SPIF)
{
SFRPAGE = SPI0_PAGE;
SPIF=0;
SPI_BUSY=0;
}
if(WCOL)
{
SFRPAGE = SPI0_PAGE;
WCOL=0;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -