这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » 国产MCU » 芯圣HC18M003单片机的模数转换例程,用IICLCD显示结果

共4条 1/1 1 跳转至

芯圣HC18M003单片机的模数转换例程,用IICLCD显示结果

专家
2023-11-08 15:39:26   被打赏 50 分(兑奖)     打赏

之前介绍了芯圣HC18M003AD外设,今天在测试IIC LCD1602显示数据的基础上,加入AD转换的测试程序。在PORTA0的外部加一个电位器分压电路,将可变端电压输入到PORTA0,通过设置PORTA0为模拟输入,利用芯片的AD外设,获得转换结果,显示到LCD1602上。使用12位模式,提供的参考电压标准为4V。

由于无法在程序中声明FloatDouble类型数据(编译报错)。所以为了实时显示电压,就把AD转换结果*1000,变成无符号长整形数,再除以4096,获得的结果,等于是人为放大了1000倍,只需要在实际显示的时候,在第一位数据后加上小数点,进而实现小数的计算。计算公式为:

Vo = ((转换结果+1) * 1000 / 4096) * 4;

电压检测电路如下

图片1.png 

程序如下,

/** 
*   模块性能介绍 
*   1、双线通讯,支持主机以及从机模式 
*   2、支持多主机通讯时钟仲裁功能 
*   3、支持地址可编程 
*   4、支持标准速率(最多100kbps)和快速(最多400kbps) 
*    
*   以IIC方式驱动LCD1602,无视中断时IIC设备的状态值,只是按顺序发送数据 
*    ************************************************************************************ 
*                   代码配置注意事项 
*     1、当CPU运行在8M时,BOR必须使能为4.2V; 
*     2、当CPU运行在4M时,BOR必须使能为3.0V及以上; 
*     3、当CPU运行在2M时,BOR必须使能为2.0V及以上,常规情况下不建议关闭BOR; 
*     4、使能BOR时除程序中修改,建议OPTION也配置相同电压。 
*   ************************************************************************************ 
* LCD1602模块:  VCC  - 5V 
*  (PCF8547)     GND 
*        SCL - P3.2 
*        SDA - P3.3 
* PCF8574T      LCD1602 
*================================================================================ 
* P7      DB7 
* P6      DB6 
* P5      DB5 
* P4      DB4 
* P3     控制背光灯 
* P0      RS 
* P1      RW 
* P2      CS 
*================================================================================ 
* LCD1602的操作 
* 写指令: RS=0, RW=0, CS(E)上升沿 
* 写数据: RS=1, RW=0, CS(E)上升沿 
*================================================================================ 
* LCD1602的操作指令 
* Bit           RS  RW   7   6   5   4   3   2   1   0           
*----------------------------------------------------------------------------------- 
*  1.清除显示    0   0   0   0   0   0   0   0   0   1 
*  2.光标返回    0   0   0   0   0   0   0   0   1   * 
*  3.设输入模式          0   0   0   0   0   0   0   1   I/D S     I/D:光标移动方向,1-右移;0-左移 
*                          S:屏幕上所有文字是否左移或右移,1表示有效,0表示无效 
*  4.显示开关    0   0   0   0   0   0   1   D   C   B     D=1开显示,D=0关显示 
*                          C=1显示光标,C=0关闭光标 
*                          B=1光标闪烁,B=0光标不闪烁 
*  5.光标字符移位        0   0   0   0   0   1   S/C R/L *   *     S/C 1-显示移动的文字,0-移动光标 
*                          R/L 左右方向 
*  6.设置功能    0   0   0   0   1   DL  N   F   *   *     DL: 1-4位总线;0-8位总线 
*                          N:  1-双行显示;0-单行显示 
*                          F:  1-5X10点阵, 0-5x7点阵 
*  7.设置字符发生器地址  0   0   0   1   字符发生器RAM    
*  8.设置数据存储器地址  0   0   1   显示数据存储器地址 
*----------------------------------------------------------------------------------- 
*  9.读忙标志或地址      0   1   BF  计数器地址 
* 10.写数到CGRAM或DDRAM  1   0   要写的数据内容  
* 11.从CGRAM或DDRAM读    1   1   读出的数据 
*=================================================================================== 
* 数据指针设置     80H + 地址码(0-27H(第一行),40H-67H(第二行)) 
** LCD1602 四线驱动方式下,一个字节数据传输2回 
**/  
  
#include"holychip_define.h"  
 
// Debug用定义
//#define DEBUG
  
//--------------OLED参数定义---------------------  
#define LINE_1_ADDR 0x40  
#define LINE_2_ADDR 0x80  
#define WIDTH     128  
#define HEIGHT     32      
  
#define OLED_CMD     0    //写命令  
#define OLED_DATA    1    //写数据   
  
#define IIC_SLAVE_ADDR           0x4E    //IIC器件地址:  
#define LCD_ADDR_W       0x4E  
#define LCD_ADDR_R       0x4F   
  
#define IIC_STATUS_START_OK      0x08    // START发送完成后的状态(ACK应答)(STA,STO,SI,AA)=(1,0,0,X)  
#define IIC_STATUS_REPEAT_START_OK      0x10     // START发送完成后的状态(ACK应答)(STA,STO,SI,AA)=(1,0,0,X)  
#define IIC_STATUS_WADDR_ACK_OK  0x18    // 向从机发送写指令+地址,发送完成后的状态(ACK应答)(STA,STO,SI,AA)=(X,0,0,X)  
#define IIC_STATUS_DATA_ACK_OK   0x28    // 向从机发送数据,完成后的状态(ACK应答)(STA,STO,SI,AA)=(0,0,0,X)  
  
#define IIC_STATUS_WADDR_NACK_OK  0x20           // 向从机发送写指令+地址,发送完成后的状态(NACK应答)(STA,STO,SI,AA)=(X,0,0,X)  
#define IIC_STATUS_DATA_NACK_OK   0x30           // 向从机发送数据,完成后的状态(NACK应答)(STA,STO,SI,AA)=(0,0,0,X)  
  
//unsigned char HEXCHR[16]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};  
  
unsigned int   gms=0;             // 延时变量  
  
/******************************************************* 
 * @说明     1毫秒单位的延时 
 * @参数     ms 毫秒数 
 * @返回值   无 
 * @注       比较准确, 
*******************************************************/  
void delay_ms(unsigned int ms) {  
    gms=ms;  
    while(gms > 0) {  
        // 等待gms = 0  
    }  
}  
  
/******************************************************* 
 * @说明      10微秒单位的延时 
 * @参数      ms 毫秒数 
 * @返回值    无 
 * @注        不准确, 
*******************************************************/  
void delay_10us(unsigned int wm) {   
    unsigned char a,b,c;  
    for(c=0; c<wm; c++) {  
        for(b=0; b<40; b++) {  
        }  
    }  
}  
  
/******************************************************* 
 * @说明    取得十六进制字符 
 * @参数    chr 字符 
 *          h_l_flag 0 - 低四位对应16进制字符;1 - 高四位对应字符 
 * @返回值  无 
 * @注      无 
*******************************************************/  
unsigned char toHexChar(unsigned char chr, unsigned char h_l_flag) {  
    unsigned char val = chr;  
    unsigned char result=0;  
      
  if (h_l_flag) {  
      val = (val & 0xF0)>>4;  
  } else {  
      val = val & 0x0f;  
  }  
    
  switch (val) {  
    case 0:  
        result = '0';break;  
    case 1:  
        result = '1';break;  
    case 2:  
        result = '2';break;  
    case 3:  
        result = '3';break;  
    case 4:  
        result = '4';break;  
    case 5:  
        result = '5';break;  
    case 6:  
        result = '6';break;  
    case 7:  
        result = '7';break;  
    case 8:  
        result = '8';break;  
    case 9:  
        result = '9';break;  
    case 10:  
        result = 'A';break;  
    case 11:  
        result = 'B';break;  
    case 12:  
        result = 'C';break;  
    case 13:  
        result = 'D';break;  
    case 14:  
        result = 'E';break;  
    case 15:  
        result = 'F';break;  
        default:  
    result = '-';break;  
    }  
    return result;  
}  
  
/******************************************************* 
 * @说明      判断字符是否能显示 
 * @参数      chr 
 * @返回值    0 - 不可显示; 1 - 可显示  
 * @注         
*******************************************************/  
unsigned char isDispChar(unsigned char chr) {   
    if (chr >= 32 && chr <= 126) {  
        return 1;  
    }  
    return 0;  
}  
  
/******************************************************* 
 * @说明    串口发送一个字符 
 * @参数    chr 字符 
 * @返回值  无 
 * @注      无 
*******************************************************/  
void send_char(unsigned char chr) {  
    SBUF = chr;         //发送8位串口数据  
    while(!TXIF);  
    TXIF = 0;        //清除发送中断标志位  
}  
  
/******************************************************* 
 * @说明    串口发送一个字符,以十六进制方式表示 
 * @参数    chr 字符 
 * @返回值  无 
 * @注      无 
*******************************************************/  
void send_char_hex(unsigned char chr) {  
    SBUF = '0';  
    while(!TXIF);  
    TXIF = 0;        //清除发送中断标志位  
  
    SBUF = 'x';  
    while(!TXIF);  
    TXIF = 0;        //清除发送中断标志位  
  
    SBUF = toHexChar(chr, 1);  
    while(!TXIF);  
    TXIF = 0;        //清除发送中断标志位  
      
    SBUF = toHexChar(chr, 0);  
    while(!TXIF);  
    TXIF = 0;        //清除发送中断标志位  
  
    SBUF = ' ';  
    while(!TXIF);  
    TXIF = 0;        //清除发送中断标志位  
}  
  
/******************************************************* 
 * @说明    串口发送一个字符,以十进制方式表示 
 * @参数    chr 字符 
 * @返回值  无 
 * @注      无 
*******************************************************/  
void send_char_dec(unsigned char chr) {  
    if (chr > 99) {  
      SBUF = toHexChar(chr/100, 0);  
      while(!TXIF);  
      TXIF = 0;        //清除发送中断标志位  
    }  
      
    if (chr > 9) {  
      SBUF = toHexChar((chr%100)/10, 0);  
      while(!TXIF);  
      TXIF = 0;        //清除发送中断标志位  
    }  
  
    SBUF = toHexChar(chr%10, 0);  
    while(!TXIF);  
    TXIF = 0;        //清除发送中断标志位  
}  
  
  
/******************************************************* 
 * @说明    串口发送一个字符串 
 * @参数    str 字符串 
 * @返回值  无 
 * @注      无 
*******************************************************/  
void send_str(unsigned char *str) {  
    unsigned char chr = '\0';  
    while (chr=*str) {  
        send_char(chr);  
        str++;  
    }  
}  
  
/******************************************************* 
 * @说明    中断服务函数 
 * @参数    无 
 * @返回值  无 
 * @注      包含定时器2中断和IIC中断 
*******************************************************/  
void interrupt all_isr(void) {  
     
    // IIC中断  
    if (IICIF) {  
       
    }  
      
//    // 串口接收中断,收到的数据存入数据缓冲区(对应两行32个字符)  
//    if(RXIF) {  
//        guc_Uartbuf  = SBUF;        // 转存8位串口接收数据  
//        guc_Uartflag = 1;           // 接收中断标志  
//          
//        // 如果是可显示的字符,保存  
//        if (isDispChar(guc_Uartbuf)) {  
//          guc_lcdchar[lcdchar_addr] = guc_Uartbuf;  
//          lcdchar_addr = (lcdchar_addr+1)%32;     // 显示位置指向下一个   
//        }  
//          
//        SCON &= ~0x10;      //禁止串口继续继续接收数据  
//        RXIF  = 0;          //清除接收中断标志位  
//    }      
      
   // 定时器0中断  
   if(T0IF) {  
       T0  = 0xF0;    //T0定时时间1ms  
       if (gms>0) {  
           gms=gms-1;  
       }  
       T0IF   = 0;    //清除T0中断标志位  
   }      
}  
  
/******************************************************* 
 * @说明      通过IIC发送一个字节给PCF8574T,PCF8574T是作为IIC从机存在的 
 * @参数      dat 呈现到 P7 ~ P0管脚上,连接到LCD引脚 
 *        P7  --  LCD160-DB7 
 *        P6  --  LCD160-DB6 
 *        P5  --  LCD160-DB5 
 *        P4  --  LCD160-DB4 
 *        P3  --  LCD1602-背光灯 
 *        P2  --  LCD1602-E 
 *        P1  --  LCD1602-RW 
 *        P0  --  LCD1602-RS 
 * @返回值    无 
 * @注        发送给LCD1602,要通过PCF8574T实现 
*******************************************************/  
unsigned char send_pcf8574Byte(unsigned char dat) {
unsigned char iic_status = 0; // 每次发送完成后获得的IIC状态码
    unsigned char result = 0;  // 返回值
    //send_str((unsigned char *)"\r\n<send_pcf8574Byte>");  
    
    // 清除IIC中断标志  
    IICIF = 0;  
    //启动IIC模块
    IICCON |= 0x40;
    delay_10us(1);
                  
    // 使IIC外设向IIC总线发送“START”信号  
    IICCON |= 0x20;       // 产生开始信号  
#ifdef DEBUG
    send_char_hex(0xA1);  
#endif
    // 等待中断发生  
    while (!IICIF);  
    iic_status=IICSTA;
#ifdef DEBUG
    send_char_hex(iic_status);  
#endif    
      
    if(iic_status == 0x08) {  
#ifdef DEBUG
      send_char_hex(0xA2);  
#endif
      // 发送子机地址    
      IICCON &=~ 0x20;       // STA=0,禁止继续发START信号  
      IICCON |= 0x04;        // AA=1,确认子机回复ACK信号?  
      IICDAT = IIC_SLAVE_ADDR;  
      IICIF = 0;  
    } else {
#ifdef DEBUG    
      send_char_hex(0xA0);  
#endif
      result = 1;  
      goto send_pcf8574Byte_end;
    }  
      
    // 等待中断发生  
    while (!IICIF);  
    iic_status=IICSTA;  
 
#ifdef DEBUG
    send_char_hex(iic_status);  
#endif
      
    if(iic_status == 0x18) {
      
#ifdef DEBUG
      send_char_hex(0xA3);  
#endif      
      // 发送数据  
      IICCON &=~ 0x20;       // STA=0,禁止继续发START信号  
      IICCON |= 0x04;        // AA=1,确认子机回复ACK信号?  
      IICDAT = dat;  
      IICIF = 0;  
    } else {
      
#ifdef DEBUG    
      send_char_hex(0xA0);  
#endif      
      result = 2;
      goto send_pcf8574Byte_end;
    }  
      
      
    // 等待中断发生  
    while (!IICIF);  
    iic_status=IICSTA;
    
#ifdef DEBUG      
    send_char_hex(iic_status);
#endif    
    if(iic_status == 0x28) {
    
#ifdef DEBUG    
      send_char_hex(0xA9);
#endif      
    } else {
    
#ifdef DEBUG    
      send_char_hex(0xA0);
#endif
      result = 3;
      goto send_pcf8574Byte_end;
    }
     
    IICCON |= 0x10;      // 停止信号
    IICCON &= ~0x40;     // 关闭IIC
    return 0;
 
send_pcf8574Byte_end:
IICCON |= 0x10;      // 停止信号
    delay_ms(1);
    IICCON &= ~0x40;     // 关闭IIC
    delay_ms(1);
    return result;
}  
  
/********************************************************* 
 * @说明      向LCD1602发送指令 
 * @参数      cmd 指令 
 * @返回值    无 
 * @注        通过PCF8574T转成引脚输出,适配LCD1602方式 
 * ----------------------------------- 
 * dat    PCF8574T          LCD1602 
 *------------------------------------ 
 * D7     P7      DB7 
 * D6     P6      DB6 
 * D5     P5      DB5 
 * D4     P4      DB4 
 * D3     P3     控制背光灯 
 * D2     P0      RS 
 * D1     P1      RW 
 * D0     P2      E  
**********************************************************/  
void write_lcd1602_cmd(unsigned char cmd) {  
    unsigned char cmd1, cmd2;  
    //send_str((unsigned char *)"\r\n<write_lcd1602_cmd>");
    
    cmd1=cmd|0x0f;  
    // 发送高4位  
    send_pcf8574Byte(cmd1 & 0xfc);    // 11111100 : CS=1,RW=0, RS=0  
    delay_10us(1);  
    send_pcf8574Byte(cmd1 & 0xf8);    // 11111000 : CS=0,RW=0, RS=0  
      
    // 发送低4位,要移位到高4位位置上  
    cmd2=cmd<<4;  
    cmd2=cmd2|0x0f;  
    send_pcf8574Byte(cmd2 & 0xfc);    // 11111100 : CS=1,RW=0, RS=0  
    delay_10us(1);  
    send_pcf8574Byte(cmd2 & 0xf8);    // 11111000 : CS=0,RW=0, RS=0  
}  
  
/************************************************************
 * @说明      向LCD1602发送数据 
 * @参数      dat 指令 
 * @返回值    无 
 * @注        通过PCF8574T转成引脚输出,适配LCD1602方式 
 * ----------------------------------- 
 * dat    PCF8574T          LCD1602 
 *------------------------------------ 
 * D7     P7      DB7 
 * D6     P6      DB6 
 * D5     P5      DB5 
 * D4     P4      DB4 
 * D3     P3     控制背光灯 
 * D2     P0      RS 
 * D1     P1      RW 
 * D0     P2      E  
**************************************************************/  
void write_lcd1602_data(unsigned char dat) {  
    unsigned char dat1, dat2;
//    send_str((unsigned char *)"\r\n<write_lcd1602_data>"); 
      
    dat1=dat|0x0f;  
    // 发送高4位  
    send_pcf8574Byte(dat1 & 0xfd);    // 11111101 : CS=1,RW=0, RS=1  
    delay_10us(1);  
    send_pcf8574Byte(dat1 & 0xf9);    // 11111001 : CS=0,RW=0, RS=1  
      
    // 发送低4位,要移位到高4位位置上  
    dat2=dat<<4;  
    dat2=dat2|0x0f;  
    send_pcf8574Byte(dat2 & 0xfd);    // 11111101 : CS=1,RW=0, RS=1  
    delay_10us(1);  
    send_pcf8574Byte(dat2 & 0xf9);    // 11111001 : CS=0,RW=0, RS=1  
}  
  
/************************************************************** 
 * @说明      初始化LCD 
 * @参数      无 
 * @返回值    无 
 * @注        无 
*****************************************************************/  
void lcd_init(void) {  
//    send_str((unsigned char *)"\r\n<lcd_init>");  
//    write_lcd1602_cmd(0x38);    // 设置显示 4 (0x38:8)
//    delay_ms(5);      
    write_lcd1602_cmd(0x33);    // 设置显示 4 (0x38:8)
    delay_ms(5);  
    write_lcd1602_cmd(0x32);    // 设置4线控制  
    delay_ms(5);
    write_lcd1602_cmd(0x28);    // 设置16*2, 5*7, 4线初始化  
    delay_ms(5);
    write_lcd1602_cmd(0x06);    // 地址加1,数据不移动,地址移动  
    delay_ms(5);
    write_lcd1602_cmd(0x0C);    // 不显示光标,光标不闪烁  
    delay_ms(5);
//    write_lcd1602_cmd(0x0f);    //  显示光标,光标闪烁  
//    delay_ms(5);
    write_lcd1602_cmd(0x01);    // 清屏  
    delay_ms(5);
    write_lcd1602_cmd(0x80);    // 起始地址  
    delay_ms(100);      
}  
  
//Y为显示指针的位置,即为各行的第几个位置,X选行  
//col:0-15  
//row:0-1  
/******************************************************************** 
 * @说明      设置显示位置 
 * @参数      row 垂直位置(0~1) 
 *    col 水平位置(0~15) 
 * @返回值    无 
 * @注        无 
********************************************************************/  
void lcd1602_GotoXY(unsigned char row, unsigned char col) {  
    if(row == 0) write_lcd1602_cmd(0x80 + col);  
    if(row == 1) write_lcd1602_cmd(0x80 + 0x40 + col);  
}  
  
  
  
/********************************************************************* 
 * @说明      使LCD在当前位置显示字符串 
 * @参数      str 字符串 
 * @返回值    无 
 * @注        无 
*********************************************************************/  
void LCD1602_Display_NoXY(unsigned char *str) {  
    //send_str((unsigned char *)"\r\n<LCD1602_Display_NoXY>str=");  
    //send_str(str);  
      
    while(*str != '\0') {  
        write_lcd1602_data(*str);
        delay_ms(5); 
        str++;  
    }  
}  
  
  
/******************************************************* 
  * @实现效果    IIC主机发送与接收 
*******************************************************/  
void main() {  
    unsigned char sta=0;
    unsigned int adc_val = 0;  //获取ADC数据
    unsigned long vol = 0;
    unsigned char val_chr[] = {'0', '\0', '\0', '\0', '\0', '\0', '\0', '0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'};   // AD转换结果
      
		/************************************系统初始化****************************************/  
		PCON   = 0x00;      //禁止WDT复位
		OSCCON  = 0x04;     //Fosc=32M Fcpu=4M(Fosc4分频 2T)      
		/************************************IO初始化*****************************************/  
		ANSELA = 0x04;      // PA4设为数字形式  , PA0为模拟口
		TRISA  = 0x04;      // PA4为输出口-中断指示
		
		ANSELC  = 0xFF;     //PC口的B0、B1、B2、B4、B6、B7为数字模式,对TSSOP20封装,只有PC0,PC1,PC2,PC4  
		// 对TSSOP20封装,PORTC2、PORTD4、PORTB6、可对应于IIC_SDA;  
		//        PORTC2和PORTB7可对应于IIC_SCK;  
		// 此处使用PORTC2和PORTC0映射为IIC的SCK和SDA  
		IICMAP  = 0x11;  
		// PORTC2为输出模式  
		//TRISC   = 0x04;  
		TRISC   = 0x05;    // PC2和PC0输出模式  
    /***********************IIC初始化**************************/  
		// IICCON构成:CR2\IICEN\STA\STO\-\AA\CR1\CR0  
		// 0x40: CR2~CR0:000,Fcpu=4M模式下,通讯速度=15.63KHz  
		//       IICEN=1,启动IIC模块  
		//       STA=0,不发送起始信号  
		//       STO=0,不发送停止信号  
		//       AA=1,回复ACK(SDA上为低电平)  
		IICCON  = 0x44;               //启动IIC模块           
		  
		/********************T0配置初始化********************/  
		OPTION  = 0X07;       // 分频寄存器配置256分频  
		T0CS    = 0;          // T0 模式选择寄存器:定时器模式,计数时钟Fcpu,休眠和绿色模式下停止  
		T0OSCEN = 0;          // 禁止定时器模块0使用计数时钟  
		T0SE    = 0;          // 定时器模式,计数时钟Fcpu  
		
		
		/********************UART配置初始化********************/  
		ANSELB = 0xC0;          //PB7 PB6设为数字模式  
		TRISB  = 0x40;          //PB7设为输入模式 PB6设为输出模式  
      
		INTMAP = 0x20;  
		UARTMAP = 0x50;         //映射 PB7口作为RX PB6口作为TX  
		// 波特率等设置  
		BRTH   = 0xFF;          
		BRTL   = 0xE6;          //Baudrate_9600  
		SCON2  = 0x24;          //UART功能选择 8位  
		SCON  |= 0x10;          //使能UART接收  
		    
		// ADCON0设置,ADON(B1=1)启动转换
		// 启动转换时,ADCIF需要先软件清0,ADCIF位为1时,置ADCST不能启动新的转换。
		// 在转换过程中,若ADCST位软件清0将终止转换
		// ADEN位置1将使能ADC模块,ADON位置1将启动一次ADC转换。
		// ADC转换完成,ADON位硬件清零,ADIF中断标志位置1,ADRESH/ADRESL寄存器值被更新。
		ADCON0  = 0x01;    // 使能ADC模块B0=1,延时20微秒再启动AD转换
		ADCON0 |= 0x00;    // AN4通道    B5~B2=0000:AN0
		// ADCON1设置
		ADCON1  = 0x20;    // ADC时钟分频Fosc/4  B6~B4=010:Fosc/4
		ADCON1 |= 0x00;    // 12位数据           B7=0:12位;B7=1:10位
		ADCON1 |= 0x02;    // ADC内部参考电压 4V B3~B1:001:4.0V
		// ADCLK设置,选择时钟 B2~B0=001:1MHz
		ADCLK   = 0x01;    // ADC转换频率为1MHz
		
		/********************中断设置********************/  
		T0IE = 1;        //打开T0中断   
		//IICIE = 1;       //允许IIC中断  
		PEIE = 1;        //允许未屏蔽中断  
		GIE = 1;         //允许总中断  
		
		send_str((unsigned char *)"\r\n<main>");  
    
		// 初始化LCD
		lcd_init();
		
		// 在第1行第一列显示字符串:Start test ... 
		lcd1602_GotoXY(0,0);
		LCD1602_Display_NoXY("Start A/D : ");
		while(1) {
		ADCON0 |= 0x02;     //启动转换 
		// ADC转换完成,ADON位硬件清零,ADIF中断标志位置1,ADRESH/ADRESL寄存器值被更新
		while(!ADIF);       // 等待AD转换完的标志
				// 获取ADC数据,12位:0-4095
				vol = (ADRESH<<8)|ADRESL;
				
				// 显示转换结果
		    // 显示结果
		    val_chr[0]=vol/1000+'0';       // 千位
		    if (val_chr[0]=='0') {
		        val_chr[0]=' ';
		    }
		    val_chr[1]=(vol%1000)/100+'0'; // 百位
		    if (val_chr[1] == '0') {
		        val_chr[1]=' ';
		    }
		    val_chr[2]=(vol%100)/10+'0';   // 十位
		    if (val_chr[2]=='0') {
		        val_chr[2]=' ';
		    }
		    val_chr[3]=vol%10+'0';         // 各位
		    val_chr[4]=' ';
		    val_chr[5]='V';
		    val_chr[6]='=';
		    // 转换为电压值
		    // 放大1000倍。将小数变整数,精确到小数点后3位,4为4V电压
		    vol = (vol+1)*1000*4/4096;
		    val_chr[7]=vol/1000 + '0';
		    val_chr[8]='.';
		    val_chr[9]=(vol%1000)/100 + '0';
		    val_chr[10]=(vol%100)/10+'0';
		    val_chr[11]=vol%10+'0';
		    val_chr[12]=0;
		    val_chr[13]=0;
		    val_chr[14]=0;
		    val_chr[15]=0;
		    lcd1602_GotoXY(1,0);
		    LCD1602_Display_NoXY(val_chr);  
		    // 延迟10ms,使LCD1602正常显示
		    
		    ADIF = 0;
    }  
}


之前发的IIC LCD测试例程中,因为在发送完数据给LCD1602后,没有预留处理时间,在频繁显示数据时,会导致屏幕显示乱码,这次加以改正。

从测试结果看,数据比较稳定,变化不大,说明芯片的AD处理部分挺好的。发上一个测试截图,由于测试周期比较小,数据变化频繁,所以显示上有频闪。

微信图片_20231108150505.jpg





关键词: 菜鸟学单片机    

院士
2023-11-08 17:41:05     打赏
2楼

版主,您这硬件环境这么不稳定,采样数据应该跳动才对啊


专家
2023-11-08 21:46:29     打赏
3楼

实测跳动时真不剧烈。我估计要么是芯片好,要么是因为采集点离芯片管脚近,要么是因为底下的铁板有屏蔽作用,能滤除一定的干扰信号?说不好,测的时间短,感觉挺稳定的。


专家
2023-11-08 21:49:09     打赏
4楼

电位器和PORTA0的距离都是最短的,短接线也是最短的。还有一种可能,是因为显示造成的延迟,使采集不密集,看不出来。总之,测量结果还不错。嘿嘿嘿。


共4条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]