找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3141|回复: 1
打印 上一主题 下一主题
收起左侧

MSP403单片机+TLC5615+ADC0808恒流源Proteus仿真程序设计

[复制链接]
跳转到指定楼层
楼主


单片机源程序如下:
  1. /******************************************************************
  2. * 实验说明:
  3. *     通设置系统主时钟(MCLK=8Mhz ) 、辅助时钟(ACLK=8Mhz )、
  4. *      子系统时钟(SMCLK=8Mhz )
  5. ******************************************************************/

  6. #include <MSP430x24x.h>
  7. #include <string.h>
  8. #define uchar unsigned char
  9. #define uint unsigned int

  10. /**************定义接口************************/
  11. #define LCDIO     P1OUT
  12. #define LCD1602_RS_1  P2OUT|=1  
  13. #define LCD1602_RS_0  P2OUT&=~1
  14. #define LCD1602_RW_1  P2OUT|=2
  15. #define LCD1602_RW_0  P2OUT&=~2
  16. #define LCD1602_EN_1   P2OUT|=4
  17. #define LCD1602_EN_0   P2OUT&=~4

  18. #define PWM_1   P2OUT|=8
  19. #define PWM_0   P2OUT&=~8

  20. /**************定义函数************************/
  21. void LCD_write_command(unsigned char command);//写入指令函数
  22. void LCD_write_dat( unsigned char dat);//写入数据函数
  23. void LCD_set_xy( unsigned char x, unsigned char y );//设置显示位置函数
  24. void LCD_dsp_char( unsigned char x,unsigned char y, char dat);//显示一个字符函数
  25. void LCD_dsp_string(unsigned char X,unsigned char Y,const char *s);//显示字符串函数
  26. void LCD_init(void);//初始化函数
  27. void delay_nms(unsigned int n);//延时函数

  28. void TCL5615_DAC(unsigned int Data);
  29. /********************************************/

  30. //变量定义
  31. unsigned char Disbuf[10],flag;

  32. unsigned int DAC_num = 5;


  33. //ADC采集函数
  34. void RefreshDis0(unsigned int Data0)
  35. {
  36.     Disbuf[0] = 0x30 + Data0/100%10;
  37.     Disbuf[1] = '.';
  38.     Disbuf[2] = 0x30 + Data0/10%10;
  39.     Disbuf[3] = 0x30 + Data0%10;
  40.     Disbuf[4] = 'V';
  41. }
  42. //ADC采集函数
  43. void RefreshDis1(unsigned int Data1)
  44. {
  45.     Disbuf[5] = 0x30 + Data1/100%10;
  46.     Disbuf[6] = '.';
  47.     Disbuf[7] = 0x30 + Data1/10%10;
  48.     Disbuf[8] = 0x30 + Data1%10;
  49.     Disbuf[9] = 'A';
  50. }

  51. void P25_Onclick( void )
  52. {
  53.     DAC_num = 5;
  54.     TCL5615_DAC( DAC_num );                      //205 对应1.0V    410  对应2.0V   5---20mA
  55.       
  56. }

  57. void P26_Onclick( void )
  58. {
  59.   //20mA
  60.    DAC_num = DAC_num + 10;
  61.    if( DAC_num > 420 )
  62.    {
  63.      DAC_num = 420;
  64.    }
  65.     TCL5615_DAC( DAC_num );                      //205 对应1.0V    410  对应2.0V   5---20mA
  66.       
  67. }

  68. void P27_Onclick( void )
  69. {
  70.    DAC_num = DAC_num - 5;
  71.    if( DAC_num < 5 )
  72.    {
  73.      DAC_num = 5;
  74.    }
  75.     TCL5615_DAC( DAC_num );                      //205 对应1.0V    410  对应2.0V   5---20mA
  76.       
  77. }

  78. //电压显示函数
  79. void Display( void )
  80. {
  81.     LCD_write_command( 0x80 );
  82.     LCD_write_dat('V');
  83.     LCD_write_dat(':');
  84.     LCD_write_dat( Disbuf[0] );
  85.     LCD_write_dat( Disbuf[1] );
  86.     LCD_write_dat( Disbuf[2] );
  87.     LCD_write_dat( Disbuf[3] );
  88.     LCD_write_dat( Disbuf[4] );
  89.     LCD_write_dat( ' ' );
  90.     LCD_write_dat( ' ' );
  91.     LCD_write_dat('I');
  92.     LCD_write_dat(':');
  93.     LCD_write_dat( Disbuf[5] );
  94.     LCD_write_dat( Disbuf[6] );
  95.     LCD_write_dat( Disbuf[7] );
  96.     LCD_write_dat( Disbuf[8] );
  97.     LCD_write_dat( Disbuf[9] );
  98. }


  99. void Display_Set( void )
  100. {
  101.    LCD_write_command( 0x80 + 0x40 );
  102.    LCD_write_dat( 'S' );
  103.    LCD_write_dat( 'e' );
  104.    LCD_write_dat( 't' );
  105.    LCD_write_dat( ':' );
  106.    LCD_write_dat( ' ' );
  107. }

  108. /*******延时函数************/
  109. void delayms(uint t)
  110. {
  111.     uint i;
  112.     while(t--)
  113.       for(i=1330;i>0;i--);//进过参数的调整
  114. }

  115. /*******检查忙函数*************/
  116. void LCD_check_busy()      //实践证明,在我的LCD1602上,检查忙指令通过率极低,以
  117. {                                          //至于不能正常使用LCD。因此我没有再用检查忙函数。而使

  118.         P1DIR=0x00;
  119.         LCDIO=0xff;
  120.         LCD1602_RS_0;                 //要用200次循环便能完成。   
  121.         LCD1602_RW_1;
  122.         LCD1602_EN_1;
  123.         while(P1IN&0x80);
  124.         LCD1602_EN_0;
  125.         P1OUT=0x00;
  126.         P1DIR=0xFF;
  127. }
  128. /******************************/

  129. /**************写指令函数********************************/  
  130. void LCD_write_command(unsigned char command)
  131. {
  132.         
  133.         LCD1602_RS_0;   
  134.         LCDIO=command;
  135.         LCD1602_EN_1;
  136.         
  137.         LCD1602_EN_0;
  138.         delayms(1);
  139.   
  140. }
  141. /***************************************************/
  142. /****************写数据函数************************/
  143. void LCD_write_dat( unsigned char dat)
  144. {
  145.       LCD1602_RS_1;
  146.       LCDIO=dat;
  147.       LCD1602_EN_1;
  148.       
  149.       LCD1602_EN_0;
  150.       delayms(1);
  151.       LCD1602_RS_0;


  152. }
  153. /****************************************************/
  154. /***************设置显示位置**************************/
  155. void LCD_set_xy( unsigned char x, unsigned char y )
  156. {
  157.         unsigned char address;
  158.         if (y == 1)
  159.              address = 0x80+x;
  160.         else if (y == 2)
  161.         {
  162.                address=0x80+0x40+x;
  163.                
  164.         }
  165.         LCD_write_command(address);
  166. }
  167. /***************************************************/
  168. /****************显示一个字符**********************/
  169. void LCD_dsp_char( unsigned char x,unsigned char y, char dat)
  170. {
  171.         LCD_set_xy( x, y );
  172.         LCD_write_dat(dat);
  173. }
  174. /**********************************************/
  175. /***************显示字符串函数***************/
  176. void LCD_dsp_string(unsigned char X,unsigned char Y,const char *s)
  177. {
  178.        uchar len,List;
  179.        len=strlen(s);
  180.        LCD_set_xy( X, Y );
  181.        for(List=0;List<len;List++)
  182.        LCD_write_dat(s[List]);
  183.       
  184. }
  185. /***********************************************/
  186. /********** 延时**********************/
  187. void delay_nms(unsigned int n)      
  188. {
  189.        unsigned int i=0,j=0;
  190.        for (i=n;i>0;i--)
  191.        for (j=0;j<1;j++);  
  192. }
  193. /**************************************/
  194. /************初始化函数****************/
  195. void LCD_init(void)
  196. {
  197.       LCD1602_RW_0;
  198.       LCD1602_EN_0;
  199.       //CLEARSCREEN;//clear screen
  200.       LCD_write_command(0x38);//set 8 bit data transmission mode
  201.       delayms(1);
  202.       LCD_write_command(0x38);//set 8 bit data transmission mode
  203.       delayms(1);
  204.       LCD_write_command(0x38);//set 8 bit data transmission mode
  205.       delayms(1);
  206.       LCD_write_command(0x06);//open display (enable lcd display)
  207.       delayms(1);
  208.       LCD_write_command(0x0C);//set lcd first display address
  209.       delayms(1);
  210.       LCD_write_command(0x01);//clear screen
  211.       delayms(1);
  212.       LCD_dsp_string(1,1,"  LCD TEST   ");//在第一行第一列显示"LCD TEST"
  213.       LCD_dsp_string(1,2,"  SUCCSEEE!  ");//在第一行第一列显示"LCD TEST"
  214.       delayms(500);
  215.       LCD_write_command(0x01);//clear screen
  216.       delayms(1);
  217. }
  218. /****************************************************/



  219. //ADC

  220. #define ADCST0          P5OUT &= ~BIT4
  221. #define ADCST1         P5OUT |= BIT4
  222. #define ADCALE0         P5OUT &= ~BIT5
  223. #define ADCALE1         P5OUT |= BIT5
  224. #define ADCEOC0         P5OUT &= ~BIT6
  225. #define ADCEOC1         P5OUT |= BIT6
  226. #define ADCOE0          P5OUT &= ~BIT7
  227. #define ADCOE1          P5OUT |= BIT7  
  228. #define ADC_Channel0          P5OUT &= ~BIT0
  229. #define ADC_Channel1          P5OUT |= BIT0
  230. unsigned int  ADC1;
  231. void ADC_START(void)
  232. {
  233.   ADCALE1;
  234.   ADCST1;
  235.   delayms(1);
  236.    ADCALE0;
  237.   ADCST0;
  238.    delayms(1);
  239. }

  240. char ADC_READ()
  241. {
  242.   uchar data;
  243.    data=0x00;
  244.    delayms(1);
  245.    ADCOE1;
  246.   ADC_START();
  247.    delayms(5);
  248.   data=P4IN;
  249.    ADCOE0;
  250.   return data;
  251. }

  252. // DAC

  253. //=============================================================================
  254. #define SET_DIN   do{P3OUT |= BIT0;}while(0)      //串行数据输入
  255. #define CLR_DIN   do{P3OUT &= ~(BIT0);}while(0)      //串行数据输入
  256. #define SET_SCLK  do{P3OUT |= BIT1;}while(0)     //串行时钟输入
  257. #define CLR_SCLK  do{P3OUT &= ~(BIT1);}while(0)     //串行时钟输入
  258. #define SET_CS    do{P3OUT |= BIT2;}while(0)      //低电平有效
  259. #define CLR_CS    do{P3OUT &= ~(BIT2);}while(0)      //低电平有效
  260. //=============================================================================

  261. /*****************************************软件延时******************************/
  262. #define CPU_F ((double)16000000)
  263. #define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0))
  264. #define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0))
  265. /*******************************************************************************/

  266. void TCL5615_DAC(unsigned int Data)
  267. {
  268.   unsigned char i;
  269.   Data <<= 6;     //移除高6位,int型数据有16位,该DA是10位
  270.   CLR_SCLK;    //在片选有效前,时钟信号要为低
  271.   CLR_CS;        //片选有效

  272.   
  273.   for(i=0;i<12;i++)       //每次转换需要10个时钟下降沿
  274.   {
  275.     if(Data&0x8000)     //取最高位数据,模拟串行数据
  276.     {
  277.       SET_DIN;
  278.       CLR_SCLK;
  279.       SET_SCLK;
  280.     }
  281.     else
  282.     {
  283.       CLR_DIN;           //数据在时钟上升沿到来前准备好
  284.       CLR_SCLK;
  285.       SET_SCLK;
  286.     }
  287.     Data <<= 1;          //数据左移,为下一次取数据做准备
  288.     CLR_SCLK;
  289.   }
  290.   
  291.   SET_CS;                    //片选失效
  292. delayms(1);
  293. }





  294. void main(void)
  295. {
  296.    
  297.     WDTCTL=WDTPW + WDTHOLD; // 关闭看门狗
  298.     P1DIR=0xFF;            // 设置方向
  299.     P1SEL=0;            // 设置为普通I/O 口
  300.    
  301.     P2DIR=0x0F;            // 设置方向
  302.    // P2SEL=0;            // 设置为普通I/O 口
  303.    
  304.     P3DIR=0xFF;            // 设置方向
  305.     //-----配合机械按键,启用内部上拉电阻-----
  306.     P2REN |= BIT5+BIT6+BIT7;                     //启用P3.5内部上下拉电阻
  307.     P2OUT |= BIT5+BIT6+BIT7;                     //将电阻设置为上拉
  308.     //-----配置P3.5中断参数-----
  309.     P2DIR &= ~BIT5+BIT6+BIT7;                    // P3.5设为输入(可省略)
  310.     P2IES |= BIT5+BIT6+BIT7;                     // P3.5设为下降沿中断
  311.     P2IE  |= BIT5+BIT6+BIT7;                    // 允许P3.5中断
  312.    
  313.    
  314.     P1OUT=0x00;
  315.    

  316.    
  317.     P5SEL = 0x00;
  318.     P5DIR |= BIT0+BIT4+BIT5+BIT6;
  319.    
  320.    
  321.     delayms(200);   
  322.     LCD_init();         //LCD1602初始化
  323.    
  324.    
  325.     /****设置AD寄存器****/
  326.     ADC12CTL0=ADC12ON+SHT0_2;//打开AD转换内核,参考电压3.3V
  327.     ADC12CTL1=SHP;
  328.     ADC12IE=0X01;//使能中断允许
  329.     ADC12CTL0|=ENC;
  330.     P6SEL|=0x01;//P6.0电压输入
  331.     P6DIR = 0xFE;
  332.     flag=0;
  333.     ADC12CTL0|=ADC12SC;//启动ADC转换器
  334.     _BIS_SR(LPM0_bits+ GIE);//进入低功耗睡眠模式
  335.    
  336.     while(1)
  337.     {
  338.       ADC1=ADC_READ();
  339.       RefreshDis1(ADC1*2);
  340.        Display();
  341.        Display_Set();
  342.      
  343.       if(flag == 1)
  344.        {
  345.           ADC12CTL0|=ADC12SC;//启动ADC转换器
  346.           flag=0;
  347.   
  348.         }
  349.       //  _BIS_SR(LPM0_bits+ GIE);//进入低功耗睡眠模式  
  350.     }  
  351. }

  352. /****ADC12中断服务****/
  353. #pragma vector=ADC12_VECTOR
  354. __interrupt void ADC12_ISR(void)
  355. {   
  356.    RefreshDis0(ADC12MEM0/8);

  357.    flag=1;
  358.    LPM0_EXIT;
  359. }

  360. /*
  361. * 名       称:P2_IODect()
  362. * 功       能:判断具体引发中断的IO,并调用相应IO的中断事件处理函数
  363. * 说       明:该函数兼容所有8个IO的检测,请根据实际输入IO激活“检测代码”。
  364. */
  365. void P2_IODect()
  366. {
  367.     unsigned int Push_Key=0;
  368.     //-----排除输出IO的干扰后,锁定唯一被触发的中断标志位-----
  369.     Push_Key=P2IFG&(~P2DIR);
  370.     //-----延时一段时间,避开机械抖动区域-----
  371.      delayms(5);                  //消抖延时
  372.     //----判断按键状态是否与延时前一致-----
  373.     if((P2IN&Push_Key)==0)                      //如果该次按键确实有效
  374.     {
  375.         //----判断具体哪个IO被按下,调用该IO的事件处理函数-----
  376.         switch(Push_Key)
  377.         {
  378.                case BIT5:     P25_Onclick();      break;
  379.                case BIT6:     P26_Onclick();      break;
  380.                case BIT7:     P27_Onclick();      break;
  381.             default:                              break;      //任何情况下均加上default
  382.         }
  383.     }
  384. }

  385. #pragma vector = PORT2_VECTOR
  386. __interrupt void PORT2_ISR(void)
  387. {
  388.     //-----启用Port2事件检测函数-----
  389.     P2_IODect();                                //检测通过,则会调用事件处理函数
  390.     P2IFG=0;                                    //退出中断前必须手动清除IO口中断标志
  391. }
复制代码

所有资料51hei提供下载:
恒流源.zip (370.56 KB, 下载次数: 93)


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:713204 发表于 2021-3-10 21:14 | 只看该作者
请问proteus用的是那个版本呀?我的打开时总是提示DSP.exe已停止工作,是不是我的版本太低了(proteus8)
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表