📄 340_ad.c
字号:
/********************************************************************
例程说明,本程序是对电位器产生的电压值进行采样,可以在寄存器观察AD的
也可以通过LCD将值显示出来,由于LV595芯片片选引脚与以太网控制芯片CP2200
中断引脚复用因些在此例程中加入了将CP2200芯片中断关闭的代码。还要在建立
工程文件时将CP220X_REG.C文件包含到工程中.
********************************************************************/
#include "C8051F340.h"
#include "CP220x_REG.h"
#define uchar unsigned char
#define uint unsigned int
#define BASE_ADDRESS 0x10
#define EMIF_TIMING 0x9E
sfr16 TMR2RL = 0xca;
sfr16 TMR2 = 0xcc;
sbit LcdCs=P0^3;
sbit led=P2^4;
bit SPI_BUSY;
uchar xdata virt_port;
uchar xdata discode;//开关显示、光标、闪烁的命令字暂存单元
uint Count1ms;
uint temp,ams,temp_l; // 存储ADC的变量
uchar xdata tab1[16]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x41,0x42,0x43,0x44
,0x45,0x46};
void ADC0_Init(void); //ADC初始化
void Timer2_Init(void); //定时器初始化
void Delay(void); //延时程序
void PORT_Init(void); //端口初始化
void delay(uint timer);
void writelcd(uchar spi_data);
void writecode(uchar ins);
void writedata(uchar d);
void lcdinit();
void lcdchar (void);
void lcdaddr(uchar DDRAM);
void cursoropen(uchar position);//开光标,关闪烁
void displayopen(void); //开显示,光标、闪烁不变
void ether_reset_low();
void ether_reset_high (void);
void Delay1ms(uint T);
void EMIF_Init (void);
void SPI_Init();
/*********************************************************************/
// 主程序
/*********************************************************************/
void main()
{
uint j;
PCA0MD &= ~0x40; //关闭看门狗
OSCICN |= 0x03; //使用内部12M晶振
ADC0_Init(); //ADC初始化
Timer2_Init(); //定时器初始化
PORT_Init(); //端口初始化
EMIF_Init ();
ether_reset_low();
for(j=0;j<5000;j++);
ether_reset_high ();
INT0EN = 0x00;
INT1EN = 0x00;
SPI_Init();
lcdinit();
IE = 0x40;
EA=1; //开中断
while(1)
{ lcdinit();
lcdchar();
} //取值此处加显示
}
/*********************************************************************/
// 延时程序
/*********************************************************************
void Delay(void)
{
int x;
for(x = 0;x < 500;x)
x++;
}
/*********************************************************************/
// 定时器2中断程序
/*********************************************************************/
void Timer2_ISR(void) interrupt 5
{
TF2H = 0; // 清除定时器2的中断标志
}
/*********************************************************************/
// ADC初始化程序
/*********************************************************************/
void ADC0_Init(void)
{
REF0CN = 0x0F; //使用内部参考电压VREF
AMX0P = 0x04; // P2.5为输入端
AMX0N = 0x1F; // 单端输入
ADC0CF = 0xFC; // 采样值右对齐,如左对齐其值为FC
ADC0CN = 0xC2; //采用定时器2溢出后3个SAR时钟开转换
// 这时MCU功耗比较低
EIE1 |= 0x08; //使能ADC中断
}
/*********************************************************************/
// ADC中断程序
/*********************************************************************/
void ADC0_ConvComplete_ISR(void) interrupt 10
{
temp= ADC0H; //高字节
ams=ADC0L; //低字节
// temp_l=temp<<8+ams;
AD0INT = 0; //清中断
}
/*********************************************************************/
// 端口初始化程序
/*********************************************************************/
void PORT_Init(void)
{
P2MDIN = 0xDF; // P2.5 为模拟输入
P2SKIP = 0x20; // P2.5 跳过
XBR0 = 0x02;
XBR1 = 0x40; // 允许交叉开关
P0MDOUT =0xff;
P1MDOUT |= 0xD8; // /WR and /RD are push-pull P3MDOUT |= 0xFF; P4MDOUT |= 0xFF;
}
/*********************************************************************/
// 定时器2初始化程序
/*********************************************************************/
void Timer2_Init(void)
{
TMR2CN = 0x00; //清定时器2标志
CKCON &= ~0xF0; //选择时基
TMR2RL = 0; // 重载值
TMR2 = 0xffff; //
ET2 = 1; // 使能定时器2 中断
TR2 = 1; // 开启定时器2
}
void delay1us(void)
{
uchar xdata i;
for(i=10;i>0;i--);
}
void SPI_Init()
{
SPI0CFG = 0x70;
SPI0CN = 0x01;
SPI0CKR = 0x3B;
}
void writelcd(uchar spi_data) //向LV595写数据以SPI方式
{
uint xdata i,j;
for(i=0;i<3;i++)
LcdCs=0;
SPI_BUSY=1;
delay1us();
SPI0DAT=spi_data;
for(j=0;j<500;j++)
{
if(!SPI_BUSY)break;
}
delay1us();
LcdCs=1;
delay1us();
delay1us();
delay1us();
delay1us();
delay1us();
delay1us();
delay1us();
for(j=0;j<5000;j++);
}
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 j,k;
uchar a,b,c,d;
temp=temp<<8;
temp_l=temp+ams;
temp_l=temp_l>>4;
a=temp_l/1000;d=temp_l%1000;
writedata(tab1[a]);
b=d/100;d=d%100;
writedata(tab1[b]);
c=d/10; d=d%10;
writedata(tab1[c]);
writedata(tab1[d]);
}
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_isr(void) interrupt 6
{
if(SPIF)
{
SPIF=0;
SPI_BUSY=0;
}
if(WCOL)
{
WCOL=0;
}
}
void ether_reset_low(){ P1 &= ~0x01; // Pull reset low}void ether_reset_high (void){ P1 |= 0x01; // Allow /RST to rise while(!(P1 & 0x01)); // Wait for /RST to go high}
void EMIF_Init (void){ EMI0CF = 0x1B; // non-muxed mode; split mode // with bank select EMI0TC = EMIF_TIMING; // This constant may be modified // according to SYSCLK to meet the // timing requirements for the CP2200 EMI0CN = BASE_ADDRESS; // Page of XRAM accessed by EMIF}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -