打印

初识MSP430 基于MSP430电子时钟的设计

[复制链接]
2462|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
cooran|  楼主 | 2012-3-8 15:28 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
今年刚刚接触TI公司研发的MSP430。看了几天的资料。就试着用C语言写了这个程序。程序并不完美。那位路人有好的建议。请留言。
本设计时钟芯片是1302.它可以支持年月日星期时间的显示。可是1302有个问题就是从23:59:59会跳到4点。这个问题要解决。
显示用的是1602.
头文件:
/*对cry1602底层驱动程序函数的声明*/
void DispStr(unsigned char x,unsigned char y,unsigned char *ptr);
void DispNChar(unsigned char x,unsigned char y, unsigned char n,unsigned char *ptr);
void LocateXY(unsigned char x,unsigned char y);
void Disp1Char(unsigned char x,unsigned char y,unsigned char data);
void LcdReset(void);
void LcdWriteCommand(unsigned char cmd,unsigned char chk);
void LcdWriteData( unsigned char data );
void WaitForEnable(void);
void Delay5ms(void);

相关帖子

沙发
cooran|  楼主 | 2012-3-8 15:29 | 只看该作者
主程序文件:

//MSP430高级实验开发组件 - DS1302时钟芯片
//硬件连接:
////       MSP430 MCU                   DS1302
////   ------------------         ------------------
////   |      P15       | ------> |     SCLK       |
////   |      P17       | ------> |      RST       |
////   |      P16       | ------> |      SDI       |
////   ------------------         ------------------
////       MSP430 MCU                   KEYS
////   ------------------         ------------------
////   ------------------         ------------------
//当前演示程序功能描述:
////
/*********************************************************/
#include <msp430x22x4.h>
#include "cry1602.h"
//88888888888888888888
typedef unsigned char uchar;
typedef unsigned int uint;
/**************宏定义***************/
#define DataDir     P4DIR
#define DataPort    P4OUT   
#define Busy     0x80
#define CtrlDir     P3DIR
#define CLR_RS P3OUT&=~BIT0;    //RS = P3.0 命令pin4
#define SET_RS P3OUT|=BIT0; //数据
#define CLR_RW P3OUT&=~BIT1; //RW = P3.1 写信号pin5
#define SET_RW P3OUT|=BIT1; //读信号
#define CLR_EN P3OUT&=~BIT2; //EN = P3.2 pin6
#define SET_EN P3OUT|=BIT2;
///8888888888888888888888
////55555555555555555555
#define DS1302_DIR P1DIR
#define DS1302_IN    P1IN
#define DS1302_OUT P1OUT
#define DS1302_RST BIT7
#define DS1302_SCLK BIT5
#define DS1302_SDI BIT6 //定义MSP320的端口
#define DS1302_RST_LO DS1302_OUT &= ~DS1302_RST
#define DS1302_RST_HI DS1302_OUT |= DS1302_RST
#define DS1302_SCLK_LO DS1302_OUT &= ~DS1302_SCLK
#define DS1302_SCLK_HI DS1302_OUT |= DS1302_SCLK
#define DS1302_SDI_LO DS1302_OUT &= ~DS1302_SDI
#define DS1302_SDI_HI DS1302_OUT |= DS1302_SDI
void DS1302_Delay(unsigned int dtime);
void DS1302_Reset(void);
void DS1302_WriteOneByte(unsigned char w_dat);
void DS1302_WriteData(unsigned char addr,unsigned char w_dat);
void DS1302_SettingData(void);
void DS1302_GetData(unsigned char *str);
unsigned char DS1302_ReadOneByte(void);
unsigned char DS1302_ReadData(unsigned char addr);
unsigned char flag=0,key_flag=0;
unsigned char Show_time(void);
//5555555555555555555555555555555555555555555555555
//lcdlcdlcdlcldcldlcldlcdlcl
/*******************************************
函数名称:Disp1Char
功    能:在某个位置显示一个字符
参    数:x--位置的列坐标
          y--位置的行坐标
          data--显示的字符数据
返回值 :无
********************************************/
void Disp1Char(uchar x,uchar y,uchar data)
{
    LocateXY( x, y );   
    LcdWriteData( data );
}
/***********************************************
函数名称:DispStr
功    能:让液晶从某个位置起连续显示一个字符串
参    数:x--位置的列坐标
          y--位置的行坐标
          ptr--指向字符串存放位置的指针
返回值 :无
***********************************************/
void DispStr(uchar x,uchar y,uchar *ptr)
{
    uchar *temp;
    uchar i,n = 0;
   
    temp = ptr;
    while(*ptr++ != '\0')   n++;    //计算字符串有效字符的个数
   
    for (i=0;i<n;i++)
    {
        Disp1Char(x++,y,temp[i]);
        if (x == 0x0f)
        {
           x = 0;
           y ^= 1;
        }
    }
}
/*******************************************
函数名称:DispNchar
功    能:让液晶从某个位置起连续显示N个字符
参    数:x--位置的列坐标
          y--位置的行坐标
          n--字符个数
          ptr--指向字符存放位置的指针
返回值 :无
********************************************/
void DispNChar(uchar x,uchar y, uchar n,uchar *ptr)
{
    uchar i;
   
    for (i=0;i<n;i++)
    {
        Disp1Char(x++,y,ptr[i]);
        if (x == 0x0f)
        {
           x = 0;
           y ^= 1;   //y取反变成0,第一行
        }
    }
}


/*******************************************
函数名称:LocateXY
功    能:向液晶输入显示字符位置的坐标信息
参    数:x--位置的列坐标 0~15
          y--位置的行坐标 0~1
返回值 :无
********************************************/
void LocateXY(uchar x,uchar y)
{
    uchar temp;
    temp = x&0x0f; //列信息
    y &= 0x01;      //行信息
    if(y)   temp |= 0x40; //如果在第2行,加0x40
   
    temp |= 0x80;//不管在第一行,第二行都要加0x80
    LcdWriteCommand(temp,1);
}
/*******************************************
函数名称:LcdReset
功    能:对1602液晶模块进行复位初始化操作
参    数:无
返回值 :无
********************************************/
void LcdReset(void)
{
    CtrlDir |= 0x07;                 //控制线端口设为输出状态
    DataDir = 0xFF;                 //数据端口设为输出状态

    LcdWriteCommand(0x38, 0);     //规定的复位操作,显示模式设置16*2
    Delay5ms();
    LcdWriteCommand(0x38, 0);
    Delay5ms();
    LcdWriteCommand(0x38, 0);
    Delay5ms();
    LcdWriteCommand(0x38, 1); //显示模式设置
    LcdWriteCommand(0x08, 1); //显示关闭
    LcdWriteCommand(0x01, 1);     //显示清屏
    LcdWriteCommand(0x06, 1); //写字符时整体不移动
    LcdWriteCommand(0x0c, 1); //显示开,不开游标,不闪烁
}


/*******************************************
函数名称:LcdWriteCommand
功    能:向液晶模块写入命令
参    数:cmd--命令,
          chk--是否判忙的标志,1:判忙,0:不判
返回值 :无
********************************************/
void LcdWriteCommand(uchar cmd,uchar chk)
{
    if (chk) WaitForEnable();   // 检测忙信号?
   
    CLR_RS; //命令
    CLR_RW;     //写信号
    _NOP();
    DataPort = cmd;             //将命令字写入数据端口
    _NOP();     
   
    SET_EN;        //P3.2为高电平             //产生使能脉冲信号
    _NOP();
    _NOP();
    CLR_EN;   //P3.2为低电平
}

/*******************************************
函数名称:LcdWriteData
功    能:向液晶显示的当前地址写入显示数据
参    数:data--显示字符数据
返回值 :无
********************************************/
void LcdWriteData( uchar data )
{
    WaitForEnable();        //等待液晶不忙
    SET_RS;      //数据
    CLR_RW;      //写信号
    _NOP();
    DataPort = data;        //将显示数据写入数据端口
    _NOP();
    SET_EN;                 //产生使能脉冲信号
    _NOP();
    _NOP();
    CLR_EN;
}

使用特权

评论回复
板凳
cooran|  楼主 | 2012-3-8 15:30 | 只看该作者
/*******************************************
函数名称:WaitForEnable
功    能:等待1602液晶完成内部操作
参    数:无
返回值 :无
********************************************/
void WaitForEnable(void)
{
    P4DIR &= 0x00; //将P4口切换为输入状态
    CLR_RS;   //命令
    SET_RW;   //读信号
    _NOP();
    SET_EN;    //使能高电平
    _NOP();
    _NOP();

    while((P4IN & Busy)!=0); //不等于0一直空执行等待,检测忙标志
    CLR_EN;
    P4DIR |= 0xFF; //将P4口切换为输出状态,以下次向1602写命令和数据
}
                       
/*******************************************
函数名称:Delay5ms
功    能:延时约5ms
参    数:无
返回值 :无
********************************************/
void Delay5ms(void)
{
    uint i=40000;
    while (i != 0)
    {
        i--;
    }
}
///lcdlcdlcdlcdlcldcllldlcdlcldlcldlcldlcl
unsigned char Setting_Time[7]={ //bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
0x09,    //--------十位-------|-------个位--------|年份(当前07年)
0x04,    //                        |-----个位-----|星期(当前周日)
0x12,    //              |十位|-------个位--------|月份(当前07月)
0x31,    //         |--十位---|-------个位--------|日期(当前01号)
0x23,    //-12H|    |--十位---|-------个位--------|小时(当前18点)
0x59,    //    |-----十位-----|-------个位--------|分钟(当前20分)
0x55    //    |-----十位-----|-------个位--------|秒钟(当前30秒)
};
unsigned char ReadingData[7]; //读出来的数据,同SettingData定义与格式
//延时函数
void DS1302_Delay(unsigned int dtime)
{
unsigned int temp;
for(temp=0;temp<100;temp++);
}
//DS1302复位
void DS1302_Reset(void)
{
DS1302_DIR |= (DS1302_RST + DS1302_SCLK);
DS1302_SCLK_LO;
DS1302_RST_LO;
DS1302_Delay(10);
DS1302_SCLK_HI;
}
//向DS1302写入一个字节
void DS1302_WriteOneByte(unsigned char w_dat)
{
unsigned char temp;

DS1302_RST_HI;
DS1302_DIR |= DS1302_SDI;

for(temp=8;temp>0;temp--) {
DS1302_SDI_LO;
if(w_dat&BIT0) DS1302_SDI_HI;
DS1302_SCLK_LO;
DS1302_Delay(10);
DS1302_SCLK_HI;
DS1302_Delay(10);
w_dat >>=1;
}
}
//从DS1302中读取一个字节
unsigned char DS1302_ReadOneByte(void)
{
unsigned char temp,rdata;
rdata = 0x00;

DS1302_RST_HI;
DS1302_DIR &= ~DS1302_SDI;

for(temp=0;temp<8;temp++)
{
   rdata >>= 1;//将移位放到前面,否则读不到最高一位
DS1302_SCLK_HI;
DS1302_Delay(10);
DS1302_SCLK_LO;
DS1302_Delay(10);
if((DS1302_IN&DS1302_SDI)==DS1302_SDI)
   rdata |= BIT7;
//rdata >>= 1;
}

return(rdata);
}
//向DS1302中写入地址后写入数据
void DS1302_WriteData(unsigned char addr,unsigned char w_dat)
{
DS1302_RST_LO;
DS1302_SCLK_LO;
DS1302_RST_HI;

DS1302_WriteOneByte(addr); //写入地址
DS1302_WriteOneByte(w_dat); //写入数据

DS1302_SCLK_HI;
DS1302_RST_LO;
}
//向DS1302写入地址后,从DS1302中读取数据
unsigned char DS1302_ReadData(unsigned char addr)
{
unsigned char r_dat;
DS1302_RST_LO;
DS1302_SCLK_LO;
DS1302_RST_HI;

DS1302_WriteOneByte(addr); //写入地址
r_dat = DS1302_ReadOneByte(); //读出数据

DS1302_SCLK_LO;
DS1302_RST_LO;

return(r_dat);
}
//按照SettingData的设置设置DS1302的时间
void DS1302_SettingData(void)
{
unsigned char temp;
unsigned char addr = 0x8C;

DS1302_WriteData(0x8E,0x00); //写入控制命令,禁用写保护
for(temp=0;temp<7;temp++)
{
DS1302_WriteData(addr,Setting_Time[temp]);
addr -= 2;
}

使用特权

评论回复
地板
cooran|  楼主 | 2012-3-8 15:30 | 只看该作者
DS1302_WriteData(0x8E,0x80); //写入控制命令,启用写保护
}
//读取DS1302时间到ReadingData中
void DS1302_GetData(unsigned char *str)
{
unsigned char temp;
unsigned char addr = 0x8D;
for(temp=0;temp<7;temp++)
{
str[temp] = DS1302_ReadData(addr);//年
addr -= 2;
}
}
//****************************显示时间子程序
unsigned char Show_time(void)
{
unsigned int p=0,q=1;
unsigned char Data[12];
unsigned char Time[9];
Data[0]=(ReadingData[0]>>4)/1+'0'; //年
Data[1]=(ReadingData[0]&0x0f)/1+'0';
Data[2]='/';
Data[3]=(ReadingData[2]>>4)/1+'0'; //月
Data[4]=(ReadingData[2]&0x0f)/1+'0';
Data[5]='/';
Data[6]=(ReadingData[3]>>4)/1+'0'; // 日
Data[7]=(ReadingData[3]&0x0f)/1+'0';
Data[8]='/';
Data[9]=(ReadingData[1]>>4)/1+'0'; // 星期
Data[10]=(ReadingData[1]&0x0f)/1+'0';
Data[11]='\0';

Time[0]=((ReadingData[4]>>4))/1+'0';// 时
Time[1]=(ReadingData[4]&0x0f)/1+'0';
Time[2]=':';
Time[3]=(ReadingData[5]>>4)/1+'0'; //分
Time[4]=(ReadingData[5]&0x0f)/1+'0';
Time[5]=':';
Time[6]=(ReadingData[6]>>4)/1+'0';// 秒
Time[7]=(ReadingData[6]&0x0f)/1+'0';
Time[8]='\0';
   
    if((Setting_Time[4]>0x04)&&(p==0))
{
    if((Time[0]=='0')&&(Time[1]=='4')&&(Time[3]=='0')&&(Time[4]=='0')&&(Time[6]=='0')&&(Time[7]=='0'))
    {
      DS1302_WriteData(0x8E,0x00); //写入控制命令,禁用写保护
      Setting_Time[4]=0x00;
      DS1302_WriteData(0x84,Setting_Time[4]);
      DS1302_WriteData(0x8E,0x80); //写入控制命令,启用写保护
     }
   
}
if((Setting_Time[4]<=0x04)&&(q==0))
{
    if((Time[0]=='0')&&(Time[1]=='4')&&(Time[3]=='0')&&(Time[4]=='0')&&(Time[6]=='0')&&(Time[7]=='0'))
    {
      DS1302_WriteData(0x8E,0x00); //写入控制命令,禁用写保护
      Setting_Time[4]=0x00;
      DS1302_WriteData(0x84,Setting_Time[4]);
      DS1302_WriteData(0x8E,0x80); //写入控制命令,启用写保护
     }
}
   if(ReadingData[4]>0x04)
   { p=0;q=0;}
   else {p=1;q=1;}
DispStr(2,0,Data);
DispStr(4,1,Time);
_NOP();
return 0;
}
//===========================时间调整=======================================
void Time_tz(void)
{
DS1302_WriteData(0x8E,0x00); //1302写入控制命令,禁用写保护
DS1302_WriteData(0x80,0x80);
DS1302_WriteData(0x8E,0x80); //1302写入控制命令,启用写保护
flag=0;
for(;;)
{
    unsigned int zsm;
    zsm=(~P2IN)&0X0f;
    if(flag==3) flag=0;
    if(zsm==0x01) flag++; //选择调整小时还是分钟
    key_flag=(~P2IN)&0x0f; //选择加调整还是减调整
//****************************************************小时调整
    if(flag==1)
    {
      LocateXY(5,1);
      LcdWriteCommand(0x0e,1);
      if(key_flag==0x02) //加
      {
        if(Setting_Time[4]>=0x23) Setting_Time[4]=0x00;
        else if((Setting_Time[4]&0x0F)==0x09) Setting_Time[4]=(Setting_Time[4]&0xf0)+0x10;
        else Setting_Time[4]+=1;
      }
      if(key_flag==0x04) //减
      {
        if(Setting_Time[4]<=0x00) Setting_Time[4]=0x23;
        else if((Setting_Time[4]&0x0F)==0x00) Setting_Time[4]=(Setting_Time[4]&0xf0)-0x10+0x09;
        else Setting_Time[4]-=1;
      }
      LocateXY(5,1);
      LcdWriteCommand(0x0e,1);
      DS1302_WriteData(0x8E,0x00); //1302写入控制命令,禁用写保护
      DS1302_WriteData(0x84,Setting_Time[4]); //写入1302修改值
      DS1302_WriteData(0x8E,0x80); //1302写入控制命令,启用写保护
      LocateXY(5,1);
      LcdWriteCommand(0x0e,1);
      DS1302_GetData(ReadingData);
      Show_time();
      LocateXY(5,1);
      LcdWriteCommand(0x0e,1);
    }
//*************************************************************分钟调整
    if(flag==2)
    {
      LocateXY(8,1);
      LcdWriteCommand(0x0e,1);
      if(key_flag==0x02) //加
      {
        if(Setting_Time[5]>=0x59) Setting_Time[5]=0x00;
        else if((Setting_Time[5]&0x0F)==0x09) Setting_Time[5]=(Setting_Time[5]&0xf0)+0x10;
        else Setting_Time[5]+=1;
      }
      if(key_flag==0x04) //减
      {
        if(Setting_Time[5]<=0x00) Setting_Time[5]=0x59;
        else if((Setting_Time[5]&0x0F)==0x00) Setting_Time[5]=(Setting_Time[5]&0xf0)-0x10+0x09;
        else Setting_Time[5]-=1;
      }
      LocateXY(8,1);
      LcdWriteCommand(0x0e,1);
      DS1302_WriteData(0x8E,0x00); //1302写入控制命令,禁用写保护
      DS1302_WriteData(0x82,Setting_Time[5]); //写入1302修改值
      DS1302_WriteData(0x8E,0x80); //1302写入控制命令,启用写保护
      LocateXY(8,1);
      LcdWriteCommand(0x0e,1);
      DS1302_GetData(ReadingData);
      Show_time();
      LocateXY(8,1);
      LcdWriteCommand(0x0e,1);
    }
    if(key_flag==0x08) {flag=0;key_flag=0;break;}
    //*******************************************************
}
DS1302_WriteData(0x8E,0x00); //1302写入控制命令,禁用写保护
DS1302_WriteData(0x80,0x00);
DS1302_WriteData(0x8E,0x80); //1302写入控制命令,启用写保护
LcdWriteCommand(0x0c,1);
}
//****************************
void main(void)
{

WDTCTL = WDTPW + WDTHOLD;
LcdReset();
DS1302_Reset();
DS1302_SettingData();
while(1)
{
    P2DIR|=0x00;
    unsigned int sm=0;
    sm=(~P2IN)&0X0f;
    if(sm==0x01)
    {
      flag=1;
      Time_tz(); //调整程序
      DS1302_WriteData(0x8E,0x00); //1302写入控制命令,禁用写保护
      DS1302_WriteData(0x80,0x00);
      DS1302_WriteData(0x8E,0x80); //1302写入控制命令,启用写保护
    }
    DS1302_GetData(ReadingData);
    Show_time(); //调用显示程序
}
//****************************/
}

使用特权

评论回复
5
yioy| | 2012-3-8 21:09 | 只看该作者
真够长的 总算看完了

使用特权

评论回复
6
yioy| | 2012-3-8 21:09 | 只看该作者
谢谢分享

使用特权

评论回复
7
壹佰| | 2012-3-9 16:35 | 只看该作者
学习一下,好长

使用特权

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

本版积分规则

个人签名:||当你停止尝试时,就是失败的时候.

36

主题

1132

帖子

29

粉丝