写这个文章是用来学习的,记录一下我的学习过程。希望我能一直坚持下去,我只是一个小白,只是想好好学习,我知道这会很难,但我还是想去做!
本文写于:2025.03.24
前言
本次笔记是用来记录我的学习过程,同时把我需要的困难和思考记下来,有助于我的学习,同时也作为一种习惯,可以督促我学习,是一个激励自己的过程,让我们开始51单片机的学习之路。
欢迎大家给我提意见,能给我的嵌入式之旅提供方向和路线,现在作为小白,我就先学习51单片机了,就跟着B站上的江协科技开始学习了.
在这里会记录下江协科技51单片机开发板的配套视频教程所作的实验和学习笔记内容,因为我之前有一个开发板,我大概率会用我的板子模仿着来做.让我们一起加油!
另外为了增强我的学习效果:每次笔记把我不知道或者问题在后面提出来,再下一篇开头作为解答!
开发板说明
本人采用的是慧净的开发板,因为这个板子是我N年前就买的板子,索性就拿来用了。不再另外购买视频中的普中开发板了。
原理图如下
视频中的都用这个开发板来实现,如果有资源就利用起来。
仔细看了看:开发板的晶振为:11.0592Mhz;12Mhz晶振是用来给CH340G芯片外置晶振;
下图是实物图
引用
51单片机入门教程-2020版 程序全程纯手打 从零开始入门
还参考了下图中的书籍:
手把手教你学51单片机(C语言版)
STC89C52手册
一、数模转换
sbit XPT2046_CS=P3^5;
sbit XPT2046_DCLK=P3^6;
sbit XPT2046_DIN=P3^4;
sbit XPT2046_DOUT=P3^7;
根据时序把值读出来
unsigned int XPT2046_ReadAD(unsigned char Command)
{
unsigned char i;
unsigned int ADValue=0;
XPT2046_DCLK=0; //不初始化也没问题
XPT2046_CS=0;
//命令字8位发送出去
for(i=0;i<8;i++)
{
XPT2046_DIN=Command&(0x80>>i);
XPT2046_DCLK=1; //满足时序>1.5us
XPT2046_DCLK=0;
}
}
//可以加一段延迟,也可不加
//调用时序连续读两个字节
for(i=0;i<16;i++)
{
XPT2046_DCLK=1; //下降沿后数据放到线上
XPT2046_DCLK=0;
if(XPT2046_DOUT){ADValue|=(0x8000>>i);}
}
XPT2046_CS=1;
return ADValue;
Command怎么写?
起始位:第一位即S位,控制字的首位必须是1,即S=1,
测+IN就是1 001 8位:1 单端:1 00 ;1001 1100 :0x9C
#define XPT2046_XP 0x9C//0x8C
#define XPT2046_YP 0xDC
#define XPT2046_VBAT 0xAC
#define XPT2046_AUX 0xEC
读取值是错误的
#include <REGX52.H>
#include "LCD1602.h"
#include "Delay.h"
#include "XPT2046.h"
unsigned int ADValue;
void main()
{
LCD_Init();
LCD_ShowString(1,1,"ADJ");
while(1)
{
ADValue=XPT2046_ReadAD( XPT2046_XP);
LCD_ShowNum(2,1,ADValue,4);
Delay(10);
}
}
if(Command&0x08)
{
return ADValue>>8;
}
else
{
return ADValue>>4;
}
#ifndef __XPT2046_H__
#define __XPT2046_H__
#define XPT2046_XP_8 0x9C//0x8C
#define XPT2046_YP_8 0xDC
#define XPT2046_VBAT_8 0xAC
#define XPT2046_AUX_8 0xEC
#define XPT2046_XP_12 0x94//0x84
#define XPT2046_YP_12 0xD4
#define XPT2046_VBAT_12 0xA4
#define XPT2046_AUX_12 0xE4
unsigned int XPT2046_ReadAD(unsigned char Command);
#endif
#include <REGX52.H>
#include "LCD1602.h"
#include "Delay.h"
#include "XPT2046.h"
unsigned int ADValue;
void main()
{
LCD_Init();
LCD_ShowString(1,1,"ADJ NTC RG ");
while(1)
{
ADValue=XPT2046_ReadAD( XPT2046_XP_8);
LCD_ShowNum(2,1,ADValue,3);
ADValue=XPT2046_ReadAD( XPT2046_YP_8);
LCD_ShowNum(2,6,ADValue,3);
ADValue=XPT2046_ReadAD( XPT2046_VBAT_8);
LCD_ShowNum(2,11,ADValue,3);
Delay(10);
}
}
DA
本身就是PWM,只不过是加了一个低通滤波
#include <REGX52.H>
#include "Delay.h"
#include "Key.h"
#include "Timer0.h"
#include "Nixie.h"
#include "Init.h"
unsigned char Counter,Compare,i;
sbit DA= P2^1;
void main()
{
Timer0_Init();
DianZhengGuan();
Compare=5;
while(1)
{
for(i=0;i<100;i++)
{
Compare=i;
Delay(10);
}
for(i=100;i>0;i--)
{
Compare=i;
Delay(10);
}
}
}
void Timer0_Routine() interrupt 1 //跳转到这里,触发中断
{
TL0 = 0xA4; //设置定时初值
TH0 = 0xFF; //设置定时初值
Counter++; //定时器定时递增
Counter%=100; //周期清零
if(Counter<Compare) //比较
{
DA=1; //给1转
}
else
{
DA=0;
}
}
PCF8591 ADC芯片(I2C)
PCF8591是一个单片集成、单独供电、低功耗、8-bit CMOS数据获取器件。PCF8591具有4个模拟输入、1个模拟输出和1个串行I²C总线接口。PCF8591的3个地址引脚A0, A1和A2可用于硬件地址编程,允许在同个I2C总线上接入8个PCF8591器件,而无需额外的硬件。在PCF8591器件上输入输出的地址、控制和数据信号都是通过双线双向I2C总线以串行的方式进行传输。
ADC实现
void PCF8591_WriteAD(unsigned char Command,float Data)
{
I2C_Start();
I2C_SendByte(PCF8591_ADDRESS);
I2C_ReceiveAck();
I2C_SendByte(Command);
I2C_ReceiveAck();
I2C_SendByte(255*(Data/5.0));
I2C_ReceiveAck();
I2C_Stop();
}
#include <REGX52.H>
#include "I2C.h"
#define PCF8591_ADDRESS 0x90 //写地址
unsigned char PCF8591_ReadAD(unsigned char Command)
{
unsigned char ADValue=0;
I2C_Start();
I2C_SendByte(PCF8591_ADDRESS);
I2C_ReceiveAck();
I2C_SendByte(Command);
I2C_ReceiveAck();
I2C_Stop();
I2C_Start();
I2C_SendByte(PCF8591_ADDRESS|0x01);
I2C_ReceiveAck();
ADValue=I2C_ReceiveByte();
I2C_SendAck(1);
I2C_Stop();
return ADValue;
}
#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "I2C.h"
#include "PCF8591.h"
#include "Init.h"
unsigned char ADValue;
float Temp;
void main()
{
LCD_Init();
LCD_ShowString(1,1,"R R T S ");
Nixie_OFF();
DianZhengGuan();
while(1)
{
ADValue=PCF8591_ReadAD(chan1);
LCD_ShowNum(2,1,ADValue,3);
Temp=(5.0*ADValue/255);
PCF8591_WriteAD(0x40,Temp);
Delay(10);
}
}
实验现象
ADC实验电阻控制LED灯的亮灭(模拟输出)
问题
1、这个芯片的自加一通道未能实现,不知道为什么尝试了很久!
总结
本节课主要学了了AD和DA,在上一节课明白了原理后,进行了实验,本次的ADC芯片,是IIC通信,不知道为什么自增的未能实现,不知道哪里出来问题,我用数组存数据,应该可以呀!