新手已经调试好几天了,MSP430做ad采样然后再LCD12864上输出的程序,还请各位大神帮忙看看

u010516912 2013-06-01 02:20:54
#include  <msp430x14x.h>
#define uchar unsigned char
#define uint unsigned int
double data;//用来存储ADC12MEM中的数据
char a,b,c=0; //用来存储将要显示在LCD上的各位数据

//初始化时钟
void initClock(void){
BCSCTL1=RSEL2+RSEL1+RSEL0+DIVA_1;//XT2开启 LFXT1工作在低频模式 ACLK 2分频( 注释:原来的人没做分频,我担心频率过高) 最高的标称频率
DCOCTL=DCO2+DCO1+DCO0;//DCO为最高频率
do{
IFG1&=~OFIFG;//清除振荡器失效标志
for(unsigned int i=255;i>0;i--);
}while(IFG1&OFIFG);//判断XT2是否起振
BCSCTL2=SELM1+SELS;//MCLK SMCLK时钟源为TX2CLK不分频
}
//延时函数
void delay(unsigned int m){
for(unsigned int i=0;i<m;i++)
_NOP();
}
void Lcd_InsWrite(uchar type,uchar transdata) //串行通信传输函数 ,transdata为要写入的数据或指令
{
uchar firsttype=0xf8; //firsttype为第一字节,用来判断是写数据还是写指令。默认是写指令
uchar temp;
uchar i,j=3;

if(type) //判断是是写数据还是写指令,0为写指令,1为写数据
firsttype=firsttype|0x02; //如果要写数据,则把第一字节的第二位至高
P1OUT|=BIT0; //给CS高电平开始写入操作
P1OUT&=~BIT2; //给SCLK时钟脉冲,在每个上升沿把数据写入到LCD
while(j>0) //把写数据指令方式和要写入的数据发送给LCD
{
if(j==3) temp=firsttype; //确认要写入第一字节数据,及数据指令判断
else if(j==2) temp=transdata&0xf0;//确认要写入第二字节数据
else temp=(transdata<<4)&0xf0; //确认要写入第三字节数据
for(i=8;i>0;i--) //把要写入的数据每个位由STD发送到LCD,写入
{
if(temp&0x80) P1OUT|=BIT1; //写入第一字节,及最高字节
else P1OUT&=~BIT1;
P1OUT|=BIT2; //给SCLK一个上升沿,写入一位
temp<<=1; //把数据指令左移一位,开始写入下一位数据
P1OUT&=~BIT2; //给SCLK一个低电平,确保下一次写入数据正常
}
delay(1); //做简单的延时
j--; //准备写入下一字节数据
}
P1OUT&=~BIT0; //写入数据指令完毕,给STD和CS低电平
P1OUT&=~BIT1;
}


//ADC12采样初始化,并打开中断子程序计算采样值的大小
void initADC12(){

P6SEL=0X01;//P6.0作为模拟输入
ADC12IE=0X01; //开放中断ADC12IFG.0
ADC12CTL0=ADC12ON+SHT0_4+REFON+REF2_5V;//打开ADC转换的核,采用内部参考电压2.5v;
ADC12CTL1=SHP; //信号源内部触发
ADC12MCTL0=SREF_1;//使用内部2.5V作为参考电压
ADC12CTL0 |=ENC; //开放使能
}


#pragma vector=ADC_VECTOR
__interrupt void ADC12ISR(){
data=ADC12MEM0*2.5/4095; //data为全局变量
Lcd_InsWrite(0,0x02);//DDRAM地址归位
}

//LCD初始化函数
//函数声明:采用MSP430端口p3.5-3.7连接LCD的E,RW,和RS端口;P4口用来传送数据
void init_lcd(void)
{
Lcd_InsWrite(0,0x30); //基本指令
delay(400);
Lcd_InsWrite(0,0x01); //清除显示
delay(400);
Lcd_InsWrite(0,0x0e);
// 显示状态设定:整体显示,游标on,游标位置反白
Lcd_InsWrite(0,0x02);//DDRAM地址归位
delay(400);
}


//将ADC转换后的值写入LCD
void WriteData(){
data*=100;
int temp=(int)data;
a=temp/100;//考虑到由于内部参考电压的限制,且仅考虑两位小数的情况
b=(temp%100)/10;
c=(temp%10);
Lcd_InsWrite(1,a+0x30);
Lcd_InsWrite(1,'.');
Lcd_InsWrite(1,b+0x30);
Lcd_InsWrite(1,c+0x30);
delay(400);
}

//主函数部分
void main(){
double temp=0.0;
WDTCTL=WDTPW+WDTHOLD;//关闭看门狗
initClock();//初始化时钟
init_lcd(); //lcd初始化
initADC12();//ADC12采样初始化,并打开中断子程序计算采样值的大小
for (;;)
{
ADC12CTL0 |= ADC12SC; // Sampling open
_BIS_SR( GIE); //关闭CPU打开总中断
}

while(1){
if(data!=temp){
temp=data;
Lcd_InsWrite(0,0x80);//确定显示位置
WriteData(); //将采样值分别计算出对应位的输出
}
}
}









...全文
1274 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
wsqyouth 2014-07-30
  • 打赏
  • 举报
回复
写的不错,不过用了哪些多口表达不清
baidu_17586423 2014-07-13
  • 打赏
  • 举报
回复
感觉还缺少一些12864显示 程序比如什么头文件#include <msp430x14x.h> //typedef unsigned char uchar; //typedef unsigned int uint; /***与msp430f149接口有关的宏定义**/ #define LCD_DataIn P4DIR=0x00 //数据口方向设置为输入 #define LCD_DataOut P4DIR=0xff //数据口方向设置为输出 #define LCD2MCU_Data P4IN #define MCU2LCD_Data P4OUT #define LCD_CMDOut P3DIR|=BIT0+BIT1+BIT2+BIT3+BIT4 //P3口的低五位设置为输出 #define LCD_RS_H P3OUT|=BIT0 //P3.0 指令寄存器 #define LCD_RS_L P3OUT&=~BIT0 //P3.0 数据寄存器 #define LCD_RW_H P3OUT|=BIT1 //P3.1 读 #define LCD_RW_L P3OUT&=~BIT1 //P3.1 写 #define LCD_EN_H P3OUT|=BIT2 //P3.2 使能 #define LCD_EN_L P3OUT&=~BIT2 //P3.2 #define LCD_RET_H P3OUT|=BIT3 #define LCD_RET_L P3OUT&=~BIT3 //LCD复位 #define LCD_PSB_H P6OUT|=BIT2 //并行传送 #define LCD_PSB_L P6OUT&=~BIT2 //串行传送 /**指令集的宏定义**/ #define BASIC_SET 0x30 //基本指令集 0x30 #define EXTEND_SET 0x34 //扩展指令集 0x34 #define DRAW_ON 0x36 //绘图显示开 0x36 #define DRAW_OFF 0x34 //绘图显示关 0x34 /******************************************* 函数名称:Delay_1ms 功 能:延时约1ms的时间 参 数:无 返回值 :无 ********************************************/ void Delay_1ms(void) { uint i; for(i = 150;i > 0;i--) _NOP(); } /******************************************* 函数名称:Delay_Nms 功 能:延时N个1ms的时间 参 数:n--延时长度 返回值 :无 ********************************************/ void Delay_Nms(uint n) { uint i; for(i = n;i > 0;i--) Delay_1ms(); } /******************************************* 函数名称:Wait_BF_0 功 能:等待BF位为0 参 数:无 返回值 :无 ********************************************/ void Wait_BF_0(void) { uchar lcdtemp; LCD_RS_L; LCD_RW_H; LCD_DataIn; do //判忙 { LCD_EN_H; _NOP(); lcdtemp = LCD2MCU_Data; LCD_EN_L; } while(lcdtemp & 0x80); } /******************************************* 函数名称:Read_Data 功 能:读取 参 数:无 返回值 :读取的数据 ********************************************/ uchar Read_Data(void) { uchar data; LCD_RS_H; LCD_RW_H; LCD_DataIn; LCD_EN_H; _NOP(); data = LCD2MCU_Data; _NOP(); _NOP(); _NOP(); _NOP(); LCD_EN_L; return data; } /******************************************* 函数名称:Write_Cmd 功 能:向液晶中写控制命令 参 数:cmd--控制命令 返回值 :无 ********************************************/ void Write_Cmd(uchar cmd) { Wait_BF_0(); LCD_DataOut; LCD_RS_L; LCD_RW_L; MCU2LCD_Data = cmd; LCD_EN_H; _NOP(); LCD_EN_L; } /******************************************* 函数名称:Write_Data 功 能:向液晶中写显示数据 参 数:dat--显示数据 返回值 :无 ********************************************/ void Write_Data(uchar dat) { Wait_BF_0(); LCD_DataOut; LCD_RS_H; LCD_RW_L; MCU2LCD_Data = dat; LCD_EN_H; _NOP(); LCD_EN_L; } /******************************************* 函数名称:Ini_Lcd 功 能:初始化液晶模块 参 数:无 返回值 :无 ********************************************/ void Ini_Lcd(void) { LCD_CMDOut; //液晶控制端口设置为输出 //LCD_RET_H; LCD_PSB_H; Delay_Nms(500); Write_Cmd(BASIC_SET); //基本指令集 Delay_1ms(); Write_Cmd(BASIC_SET); //基本指令集 Delay_1ms(); Write_Cmd(0x02); // 地址归位 Delay_1ms(); Write_Cmd(0x0c); //整体显示打开,游标关闭 Delay_1ms(); Write_Cmd(0x01); //清除显示 Delay_1ms(); Write_Cmd(0x06); //游标右移 Delay_1ms(); Write_Cmd(0x80); //设定显示的起始地址 } /******************************************* 函数名称:Disp_HZ 功 能:控制液晶显示汉字 参 数:addr--显示位置的首地址 pt--指向显示数据的指针 num--显示字符个数 返回值 :无 ********************************************/ void Disp_HZ(uchar addr,uchar * pt,uchar num) { uchar i; Write_Cmd(addr); for(i = 0;i < (num*2);i++) Write_Data(*(pt++)); } /******************************************* 函数名称:Disp_Str 功 能:控制液晶显示汉字 参 数:addr--显示位置的首地址 pt--指向显示数据的指针 num--显示字符个数 返回值 :无 ********************************************/ void Disp_Str(uchar addr,uchar * pt,uchar num) { uchar i; Write_Cmd(addr); for(i=0;i<num;i++) Write_Data(*(pt++)); } /******************************************* 函数名称:Disp_Char 功 能:控制液晶显示字符 参 数:addr:显示字字的位置 Char:要显示的字符 i:1:显示在该地址的高八位0:显示在该地址的低八位 返回值 :无 ********************************************/ void Disp_Char(uchar addr,uchar Char,uchar i) { uchar tmp; if(i==0) { Write_Cmd(addr); Write_Data(Char); } else { Write_Cmd(addr); tmp=Read_Data(); Write_Cmd(addr); Write_Data(tmp); Write_Data(Char); } } /******************************************* 函数名称:Clear_GDRAM 功 能:清除液晶GDRAM中的随机数据 参 数:无 返回值 :无 ********************************************/ void Clear_GDRAM(void) { uchar i,j,k; Write_Cmd(EXTEND_SET); //打开扩展指令集 /***先清除上半屏***/ i = 0x80; for(j = 0;j < 32;j++) { Write_Cmd(i++); //先写竖坐标 Write_Cmd(0x80); //再写横坐标 for(k = 0;k < 16;k++)//横向写8个字,横向地址是自动加的 { Write_Data(0x00); } } /****再清除下半屏***/ i = 0x80; for(j = 0;j < 32;j++) { Write_Cmd(i++); Write_Cmd(0x88); for(k = 0;k < 16;k++) { Write_Data(0x00); } } Write_Cmd(BASIC_SET); //回到基本指令集 } /******************************************* 函数名称:fan_bai 功 能:将i个汉字进行反白 参 数:Yaddr--Y地址(它只能是(0~24)) Xaddr--X地址(它只能是0x80到0x9f) i--反白汉字的个数 返回值 :无 ********************************************/ void fan_bai(uchar Yaddr,uchar Xaddr,uchar i) { uchar j,k,h; // Write_Cmd(0x01); //清屏,只能清除DDRAM Write_Cmd(EXTEND_SET); //使用扩展指令集,关闭绘图显示 h=Yaddr; for(k=0;k<i;k++) { Yaddr=h; for(j=0;j<16;j++) { Write_Cmd(0x80+(Yaddr++)); //Y地址 Write_Cmd(Xaddr+k); //X地址 Write_Data(0xff); Write_Data(0xff); } } Write_Cmd(DRAW_ON); //打开绘图显示 Write_Cmd(BASIC_SET); //回到基本指令集模式 }
shenleiwhu 2013-06-05
  • 打赏
  • 举报
回复
楼主要多多努力啊,可以逐行调试
u010516912 2013-06-01
  • 打赏
  • 举报
回复
引用 2 楼 u010912035 的回复:
我这里也是AD转换不成功,
这个是成功的,拿着直接可以用吧
#include  <msp430x14x.h>
#define uchar unsigned char
#define uint unsigned int
static  double data;//用来存储ADC12MEM中的数据
  char a,b,c=0; //用来存储将要显示在LCD上的各位数据

//初始化时钟
void initClock(void){
  BCSCTL1=RSEL2+RSEL1+RSEL0+DIVA_1;//XT2开启 LFXT1工作在低频模式 ACLK 2分频( 注释:原来的人没做分频,我担心频率过高) 最高的标称频率
  DCOCTL=DCO2+DCO1+DCO0;//DCO为最高频率
  do{
    IFG1&=~OFIFG;//清除振荡器失效标志
    for(unsigned int i=255;i>0;i--);
  }while(IFG1&OFIFG);//判断XT2是否起振
  BCSCTL2=SELM1+SELS;//MCLK SMCLK时钟源为TX2CLK不分频
}
//延时函数
void delay(unsigned int m){
for(unsigned int i=0;i<m;i++);
}



//串行传送一字节数据
void SendByte(uchar dat)
{
	uchar i;
	P1SEL=0x00;//P1口设置为一般的I/O口
	P1DIR=0xff;//P1口所有引脚设置为输出方向
	for(i=0;i<8;i++)
	{
		P1OUT&=~BIT0;
		if((dat&0x80)!=0)
			P1OUT|=BIT1;
		else
			P1OUT&=~BIT1;
		P1OUT|=BIT0;
		dat=dat<<1;
	}
}


//写控制指令
void SendCMD(uchar dat)
{
	P1SEL=0x00;
	P1DIR=0xff;
	
	P1OUT|=BIT2;
	SendByte(0xf8);
	SendByte(dat&0xf0);
	SendByte((dat<<4)&0xf0);
	P1OUT&=~BIT2;
}



//写显示数据
void SendData(uchar dat)
{
	P1SEL=0x00;
	P1DIR=0xff;
	
	P1OUT|=BIT2;
	SendByte(0xfa);
	SendByte(dat&0xf0);
	SendByte((dat<<4)&0xf0);
	P1OUT&=~BIT2;
}


void init_lcd(void)
{
	delay(400);
	SendCMD(0x30);//功能设置,一次送8位数据,基本指令集
	SendCMD(0x04);//点设定,显示字符,光标从左到右移位,DDRAM地址加一
	SendCMD(0x0c);//显示设定,开显示,不显示光标,当前显示位不反白闪动
        SendCMD(0x02);//DDRAM地址归位
        SendCMD(0x01);//清DDRAM
}

//ADC12采样初始化,并打开中断子程序计算采样值的大小
void initADC12(){

P6SEL=0X01;//P6.0作为模拟输入 
ADC12IE=0X01; //开放中断ADC12IFG.0
ADC12CTL0=ADC12ON+SHT0_4+REFON+REF2_5V;//打开ADC转换的核,采用内部参考电压2.5v;
ADC12CTL1=SHP;   //信号源内部触发
ADC12MCTL0=SREF_1;//使用内部2.5V作为参考电压
ADC12CTL0 |=ENC;  //开放使能
}

#pragma vector=ADC_VECTOR
__interrupt void ADC12ISR(){
data=ADC12MEM0*2.5/4095;  //data为全局变量
SendCMD(0x02); 
_BIC_SR_IRQ(CPUOFF);                    // Clear CPUOFF bit from 0(SR)
}

void SendDouble(double data){
data*=100;
int temp=(int)data;
a=temp/100;//考虑到由于内部参考电压的限制,且仅考虑两位小数的情况
b=(temp%100)/10;
c=(temp%10);
SendData(a+0x30);
SendData('.');
SendData(b+0x30);
SendData(c+0x30);
SendData(' ');
SendData('V');
}

//主函数部分
void main(){	
double temp=0.0;  
WDTCTL=WDTPW+WDTHOLD;//关闭看门狗

initClock();//初始化时钟
initADC12();
init_lcd(); //lcd初始化
 while(1)
  {
     ADC12CTL0 |= ADC12SC;                   // Sampling open
    _BIS_SR(CPUOFF + GIE);                  // LPM0, ADC12_ISR will force exit
        if(temp!=data)
    {
      temp=data;
      SendDouble(data);
    }
  }}
u010516912 2013-06-01
  • 打赏
  • 举报
回复
引用 2 楼 u010912035 的回复:
我这里也是AD转换不成功,
ADC那段是死循环的; 那个地方我给重新写了下;

//ADC12采样初始化,并打开中断子程序计算采样值的大小
void initADC12(){

P6SEL=0X01;//P6.0作为模拟输入 
ADC12IE=0X01; //开放中断ADC12IFG.0
ADC12CTL0=ADC12ON+SHT0_4+REFON+REF2_5V;//打开ADC转换的核,采用内部参考电压2.5v;
ADC12CTL1=SHP;   //信号源内部触发
ADC12MCTL0=SREF_1;//使用内部2.5V作为参考电压
ADC12CTL0 |=ENC;  //开放使能
}


#pragma vector=ADC_VECTOR
__interrupt void ADC12ISR(){
data=ADC12MEM0*2.5/4095;  //data为全局变量
Lcd_InsWrite(0,0x02); 
_BIC_SR_IRQ(CPUOFF);                    // Clear CPUOFF bit from 0(SR)
}
相应的主函数修改成
initADC12();//ADC12采样初始化,并打开中断子程序计算采样值的大小

while(1){
  if(data!=temp){
 temp=data;   
WriteData(); //将采样值分别计算出对应位的输出
    ADC12CTL0 |= ADC12SC;                   // Sampling open
    _BIS_SR( GIE);                 //关闭CPU打开总中断
}
但是仍然出问题
u010912035 2013-06-01
  • 打赏
  • 举报
回复
我这里也是AD转换不成功,
u010516912 2013-06-01
  • 打赏
  • 举报
回复
我调试了一下,AD转换好像没成功;而且LCD输出不对啊

27,373

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧