找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6670|回复: 4
收起左侧

[求助]AD转换结果输出到1602上乱码

[复制链接]
ID:27772 发表于 2011-1-12 01:09 | 显示全部楼层 |阅读模式

代码如下,第一行正常显示,第二行乱码

 

  1. <br>1 #include<STC12C5A60S2.H> <br>2 #include<intrins.h> <br>3 <br>4 #define uchar unsigned char <br>5 #define uint unsigned int <br>6 <br>7 unsigned int temp1,sh1,ge1,n1,m1; <br>8 unsigned char ad_result_data[10]; //AD转换高八位 <br>9 unsigned char ad_result_low2[10]; //AD转换低八位 <br>10 unsigned char ad_result_total[10]; //AD转换总十位 <br>11 unsigned char ad_average_result; //AD转换十次的平均值 <br>12 unsigned char Ain,Vin; <br>13 unsigned int temp1,sh1,ge1,n1,m1; <br>14 char tp=0; <br>15 <br>16 //===============================LCD1602接口定义===================== <br>17 <br>18 //定义引脚 <br>19 #define LCM_Data P0 //数据接口 <br>20 #define Busy 0x80 //用于检测LCM状态字中的Busy标识 <br>21 sbit LCM_RS = P2^2; //寄存器选择输入端 <br>22 sbit LCM_RW = P2^3; //读写控制输入端 <br>23 sbit LCM_E = P2^4; //使能信号输入端 <br>24 <br>25 void WriteDataLCM(unsigned char WDLCM); <br>26 void WriteCommandLCM(unsigned char WCLCM,BuysC); <br>27 unsigned char ReadDataLCM(void); <br>28 unsigned char ReadStatusLCM(void); <br>29 void LCMInit(void); <br>30 void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData); <br>31 void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData); <br>32 void Delay5Ms(void); <br>33 void Delay400Ms(void); <br>34 void AD_initiate(); <br>35 void ADC_Power_On(); <br>36 void get_ad_result(); <br>37 void caiyangP10(); <br>38 <br>39 void main(void) <br>40 { <br>41 Delay400Ms(); //启动等待,等LCM讲入工作状态 <br>42 LCMInit(); //LCM初始化 <br>43 Delay5Ms(); //延时片刻(可不要) <br>44 AD_initiate(); //初始化 <br>45 ADC_Power_On(); //开AD电源 <br>46 <br>47 DisplayListChar(0, 0, "ADCTest"); <br>48 Delay5Ms(); <br>49 DisplayListChar(0, 1, "GAGA"); <br>50 //ReadDataLCM();//测试用句无意义 <br>51 while(1){ <br>52 &nbsp;&nbsp;&nbsp;&nbsp;caiyangP10(); <br>53 &nbsp;&nbsp;&nbsp;&nbsp;DisplayListChar(0, 1, Vin ); <br>54 &nbsp;&nbsp;&nbsp;&nbsp;Delay400Ms(); <br>55 } <br>56 } <br>57 <br>58 //写数据 <br>59 void WriteDataLCM(unsigned char WDLCM) <br>60 { <br>61 ReadStatusLCM(); //检测忙 <br>62 LCM_Data = WDLCM; <br>63 LCM_RS = 1; <br>64 LCM_RW = 0; <br>65 LCM_E = 0; //若晶振速度太高可以在这后加小的延时 <br>66 LCM_E = 0; //延时 <br>67 LCM_E = 1; <br>68 } <br>69 <br>70 //写指令 <br>71 void WriteCommandLCM(unsigned char WCLCM,BuysC) //BuysC为0时忽略忙检测 <br>72 { <br>73 if (BuysC) ReadStatusLCM(); //根据需要检测忙 <br>74 LCM_Data = WCLCM; <br>75 LCM_RS = 0; <br>76 LCM_RW = 0; <br>77 LCM_E = 0; <br>78 LCM_E = 0; <br>79 LCM_E = 1; <br>80 } <br>81 <br>82 //读数据 <br>83 unsigned char ReadDataLCM(void) <br>84 { <br>85 LCM_RS = 1; <br>86 LCM_RW = 1; <br>87 LCM_E = 0; <br>88 LCM_E = 0; <br>89 LCM_E = 1; <br>90 return(LCM_Data); <br>91 } <br>92 <br>93 //读状态 <br>94 unsigned char ReadStatusLCM(void) <br>95 { <br>96 LCM_Data = 0xFF; <br>97 LCM_RS = 0; <br>98 LCM_RW = 1; <br>99 LCM_E = 0; <br>100 LCM_E = 0; <br>101 LCM_E = 1; <br>102 while (LCM_Data &amp; Busy); //检测忙信号 <br>103 return(LCM_Data); <br>104 } <br>105 <br>106 void LCMInit(void) //LCM初始化 <br>107 { <br>108 LCM_Data = 0; <br>109 WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号 <br>110 Delay5Ms(); <br>111 WriteCommandLCM(0x38,0); <br>112 Delay5Ms(); <br>113 WriteCommandLCM(0x38,0); <br>114 Delay5Ms(); <br>115 <br>116 WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号 <br>117 WriteCommandLCM(0x08,1); //关闭显示 <br>118 WriteCommandLCM(0x01,1); //显示清屏 <br>119 WriteCommandLCM(0x06,1); // 显示光标移动设置 <br>120 WriteCommandLCM(0x0C,1); // 显示开及光标设置 <br>121 } <br>122 <br>123 //按指定位置显示一个字符 <br>124 void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData) <br>125 { <br>126 Y &amp;= 0x1; <br>127 X &amp;= 0xF; //限制X不能大于15,Y不能大于1 <br>128 if (Y) X |= 0x40; //当要显示第二行时地址码+0x40; <br>129 X |= 0x80; // 算出指令码 <br>130 WriteCommandLCM(X, 0); //这里不检测忙信号,发送地址码 <br>131 WriteDataLCM(DData); <br>132 } <br>133 <br>134 //按指定位置显示一串字符 <br>135 void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData) <br>136 { <br>137 unsigned char ListLength; <br>138 <br>139 ListLength = 0; <br>140 Y &amp;= 0x1; <br>141 X &amp;= 0xF; //限制X不能大于15,Y不能大于1 <br>142 while (DData[ListLength]>0x20) //若到达字串尾则退出 <br>143 { <br>144 if (X <= 0xF) //X坐标应小于0xF <br>145 { <br>146 DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符 <br>147 ListLength++; <br>148 X++; <br>149 } <br>150 } <br>151 } <br>152 <br>153 //5ms延时 <br>154 void Delay5Ms(void) <br>155 { <br>156 unsigned int TempCyc = 5552; <br>157 while(TempCyc--); <br>158 } <br>159 <br>160 //400ms延时 <br>161 void Delay400Ms(void) <br>162 { <br>163 unsigned char TempCycA = 5; <br>164 unsigned int TempCycB; <br>165 while(TempCycA--) <br>166 { <br>167 TempCycB=7269; <br>168 while(TempCycB--); <br>169 }; <br>170 } <br>171 <br>172 /************************AD转换结束***********************/ <br>173 void AD_initiate() //初始化函数 <br>174 { <br>175 ES=0; <br>176 TMOD=0x21; //定时计数器方式控制寄存器,"自动重装,16位计数器". <br>177 SCON=0x50; //串行控制寄存器,方便在串口助手那观察 <br>178 TH1=0xfa; <br>179 TL1=0xfa; <br>180 TR1=1; <br>181 } <br>182 <br>183 void ADC_Power_On() //AD转换电 <br>184 { <br>185 ADC_CONTR |= 0x80; <br>186 Delay5Ms(); //必要的延时 <br>187 } <br>188 <br>189 void get_ad_result() //取AD结果函数,它是十位AD转换,每十次平均,最后取低八位作为AD采样数据 <br>190 { <br>191 uint i,q=0; <br>192 for(i=0;i<10;i++) <br>193 { <br>194 tp=0; <br>195 ADC_RES=0; //高八位数据清零,STC12C5A60S2 AD数据寄存名与STC12C54××系列不同 <br>196 ADC_RESL=0; //低两位清零 <br>197 ADC_CONTR|=0x08; //启动AD转换 <br>198 while(!tp) //判断AD转换是否完成 <br>199 { <br>200 tp=0x10; <br>201 tp&amp;=ADC_CONTR; <br>202 } <br>203 ADC_CONTR&amp;=0xe7; <br>204 ad_average_result=ADC_RES; <br>205 q=q+ad_average_result; <br>206 } <br>207 ad_average_result=q/10; <br>208 //ad_average_result=ad_average_result*4*5000/1024; <br>209 } <br>210 /************************AD转换结束***********************/ <br>211 <br>212 //---------------------电压采样程序------------------------- <br>213 <br>214 void caiyangP10() //测电压 <br>215 { <br>216 P1M0|=0x01; //设P1_0为开漏模式 如: P1_0= #00000000B <br>217 P1M1|=0x01; <br>218 ADC_CONTR=0xe0; //设置P1.0为输入AD转换口 <br>219 Delay5Ms(); <br>220 get_ad_result(); //取转换数据 <br>221 Vin=ad_average_result; <br>222 }
复制代码

[此贴子已经被作者于2011-1-12 1:11:55编辑过]
回复

使用道具 举报

ID:27770 发表于 2011-1-12 11:14 | 显示全部楼层

建议你:

1.先解决 1602 显示的问题,这个事情与是否 AD 或是其它内容没有直接联系.做一个测试程序,让 1602 先正常显示 2 行字.(不算难的工作.)

2.上面解决后,把 AD 转换结果拷贝到 1602 测试程序,看看是否正常.如果原来测试正常,后来不正常,则是 AD 数据可能格式不对,或者数据过大.(AD 数据原始是 HEX 码,你需要处理后给 1602 .)

3.上面正常后,停止测试.把测试部分显示移植到你项目去.----这样不会再出错了吧?

积木式的工作顺序,特别是如果你第一次使用 1602 ,更应该这么做.养成好习惯------其它新东西也是这种做法.

4.提示: 12C5A 的 AD 结果有 2 种选择,它们组合  2 个数据字节得到 10BIT 数据,检查一下你的组合是否正确.(弄错了就会大大超过 10BIT 非正常结果.)

仅供参考!

回复

使用道具 举报

ID:27772 发表于 2011-1-15 16:51 | 显示全部楼层
谢谢你,我发现是数据类型错了,直接写int的,1602会当做指令处理了,增加了一个switch语句,把原始数据转换成一位一位的,显示出来 就ok了,不过发现这款单片机AD转换线性不够好,误差比较大
回复

使用道具 举报

ID:27770 发表于 2011-1-16 14:29 | 显示全部楼层

祝贺你的成功!----毕竟,论坛的帮助很有限,主要还是靠你自己的努力!

STC12C5A60S2  ----包括许多牌子的单片机自带的 AD 效果都不怎么好,如果你希望依靠它作出比较好的效果来,是要付出比较大的努力的!

把你的测量范围分割为 100 份,甚至 1000 份.每一份单独测量出来,取16次平均值,作为标准.制定一个表格,然后,把 AD 读数通过查表去得到实际电压数据.---表格越多越是精确,越是辛苦!

要不要试一下?

仅供参考!

回复

使用道具 举报

ID:80407 发表于 2015-6-8 07:22 | 显示全部楼层
楼主,你好!我的ADC0809的数据输入口和液晶屏的数据口都用的P0口但是ADC0809加了一个锁存器,但是还是出现乱码的情况,请问这样怎么办啊?
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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