IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 用电位器AD/DA控制舵机(SG090)------51单片机基础篇(程序粗糙待优化) -> 正文阅读

[嵌入式]用电位器AD/DA控制舵机(SG090)------51单片机基础篇(程序粗糙待优化)

首先认识一下电位器和舵机如下图
在这里插入图片描述

如何通过电位器控制舵机,让舵机随着电位器的旋转而跟着转动呢,整个思路是这样的,先采集电位器的信号,然后通过类比信号输出PWM来控制舵机的转动,下面我们来进行第一步,采集电位器信号。
/以下是采集电位器过程*************/

我们要采集电位器信号首先要认识XPT2046,如下图在这里插入图片描述
我们可以看到他有四个模式配置管脚(P34–P37)和四个采集通道(AIN0–AIN3),具体的工作方式很复杂,要了解的话要查阅对应的手册,而我们要用它的话其实不用这么麻烦,只要会配置让他读出并且返回电位器的值就行了,下面直接上程序
XPT2026.c文件
#include <REGX52.H>
#include <INTRINS.H>

//引脚定义
sbit XPY2046_DIN=P3^4;
sbit XPY2046_CS=P3^5;
sbit XPY2046_DCLK=P3^6;
sbit XPY2046_DOUT=P3^7;

/**

  • @brief ZPT2046读取AD值
  • @param Command 命令字,范围:头文件内定义的宏,结尾的数字表示转换的位数
  • @retval AD转换后的数字量,范围:8位为0255,12位为04095
    */
    unsigned int XPT2046_ReadAD(unsigned char Command)
    {
    unsigned char i;
    unsigned int Data=0;
    XPY2046_DCLK=0;
    XPY2046_CS=0;
    for(i=0;i<8;i++)
    {
    XPY2046_DIN=Command&(0x80>>i);
    XPY2046_DCLK=1;
    XPY2046_DCLK=0;
    }
    for(i=0;i<16;i++)
    {
    XPY2046_DCLK=1;
    XPY2046_DCLK=0;
    if(XPY2046_DOUT){Data|=(0x8000>>i);}
    }
    XPY2046_CS=1;
    // if(Command&0x08)
    // {
    return Data>>8;
    // }
    //
    // else
    // {
    // return Data>>4;
    // }

}

XPT2026.h文件
#ifndef XPT2046_H
#define XPT2046_H

#define XPT2046_VBAT 0xAC
#define XPT2046_AUX 0xEC
#define XPT2046_XP 0x9C //0xBC
#define XPT2046_YP 0xDC

#define XPT2046_VBAT_16 0xA4
#define XPT2046_AUX_16 0xE4
#define XPT2046_XP_16 0x94 //0xBC
#define XPT2046_YP_16 0xD4

unsigned int XPT2046_ReadAD(unsigned char Command);

#endif

以上我们就配置好了XPT2046,还配置好了12位的哦,而我们今天用的是读取的是8位

继续
配置好了怎么用?接下来写main.c文件
#include <REGX52.H>
#include “Delay.h”
#include “LCD1602.h”
#include “XPT2046.h”

sbit LED1=P2^2;
sbit beep=P2^5;
sbit DA=P2^1;
sbit pwm=P1^0;

unsigned int ADValue,ADValue1,ADValue2,ADValue4;
unsigned char Counter,Compare;

void main(void)
{
Timer0_Init();
LCD_Init();
LCD_ShowString(1,1,“ADJ NTC GR”);
while(1)
{
ADValue=XPT2046_ReadAD(XPT2046_XP); //读取AIN0,可调电阻
ADValue4=6+(ADValue/20);
LCD_ShowNum(2,1,ADValue,3); //显示AIN0
ADValue1=XPT2046_ReadAD(XPT2046_YP); //读取AIN1,热敏电阻
LCD_ShowNum(2,6,ADValue1,3); //显示AIN1
ADValue2=XPT2046_ReadAD(XPT2046_VBAT); //读取AIN2,光敏电阻
LCD_ShowNum(2,11,ADValue2,3); //显示AIN2
Delay(100);
if(ADValue2>150)
{
LED1=1;
}
else
{
LED1=0;
}
if(ADValue1>=140)
{
beep=1;
}
else
{
beep=0;
}

}

}

void Timer0_Routine() interrupt 1
{
TL0 = 0x9C; //设置定时初值
TH0 = 0xFF; //设置定时初值
Counter++;
Counter%=255; //计数值变化范围限制在0~99

if(Counter<ADValue)	//计数值小于比较值
{
	DA=1;		//输出1
}
else				//计数值大于比较值
{
	DA=0;		//输出0
}
	if(Counter<ADValue4)	//计数值小于比较值
{
	pwm=1;		//输出1
}
else				//计数值大于比较值
{
	pwm=0;		//输出0
}

}

由于我们使用了定时器,接下来配置定时器Timer0.c文件
#include <REGX52.H>

/**

  • @brief 定时器0初始化,100us@12.000MHz
  • @param 无
  • @retval 无
    */
    void Timer0_Init(void)
    {
    TMOD &= 0xF0; //设置定时器模式
    TMOD |= 0x01; //设置定时器模式
    TL0 = 0x9C; //设置定时初值
    TH0 = 0xFF; //设置定时初值
    TF0 = 0; //清除TF0标志
    TR0 = 1; //定时器0开始计时
    ET0=1;
    EA=1;
    PT0=0;
    }

/*定时器中断函数模板
void Timer0_Routine() interrupt 1
{
static unsigned int T0Count;
TL0 = 0x9C; //设置定时初值
TH0 = 0xFF; //设置定时初值
T0Count++;
if(T0Count>=1000)
{
T0Count=0;

}

}
*/

Timer0.h文件
#ifndef TIMER0_H
#define TIMER0_H

void Timer0_Init(void);

#endif

还有延时函数文件Delay.c文件

void Delay(unsigned int xms)
{
unsigned char i, j;
while(xms–)
{
i = 2;
j = 239;
do
{
while (–j);
} while (–i);
}
}

Delay.h文件
#ifndef DELAY_H
#define DELAY_H

void Delay(unsigned int xms);

#endif

然后,最后的最后,,相信大家都看到了我们用了LCD1602显示模块,,哈哈哈,那我们继续
LCD1602.c文件
#include <REGX52.H>

//引脚配置:
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
#define LCD_DataPort P0

//函数定义:
/**

  • @brief LCD1602延时函数,12MHz调用可延时1ms

  • @param 无

  • @retval 无
    */
    void LCD_Delay()
    {
    unsigned char i, j;

    i = 2;
    j = 239;
    do
    {
    while (–j);
    } while (–i);
    }

/**

  • @brief LCD1602写命令
  • @param Command 要写入的命令
  • @retval 无
    */
    void LCD_WriteCommand(unsigned char Command)
    {
    LCD_RS=0;
    LCD_RW=0;
    LCD_DataPort=Command;
    LCD_EN=1;
    LCD_Delay();
    LCD_EN=0;
    LCD_Delay();
    }

/**

  • @brief LCD1602写数据
  • @param Data 要写入的数据
  • @retval 无
    */
    void LCD_WriteData(unsigned char Data)
    {
    LCD_RS=1;
    LCD_RW=0;
    LCD_DataPort=Data;
    LCD_EN=1;
    LCD_Delay();
    LCD_EN=0;
    LCD_Delay();
    }

/**

  • @brief LCD1602设置光标位置
  • @param Line 行位置,范围:1~2
  • @param Column 列位置,范围:1~16
  • @retval 无
    */
    void LCD_SetCursor(unsigned char Line,unsigned char Column)
    {
    if(Line1)
    {
    LCD_WriteCommand(0x80|(Column-1));
    }
    else if(Line
    2)
    {
    LCD_WriteCommand(0x80|(Column-1+0x40));
    }
    }

/**

  • @brief LCD1602初始化函数
  • @param 无
  • @retval 无
    /
    void LCD_Init()
    {
    LCD_WriteCommand(0x38);//八位数据接口,两行显示,5
    7点阵
    LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关
    LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动
    LCD_WriteCommand(0x01);//光标复位,清屏
    }

/**

  • @brief 在LCD1602指定位置上显示一个字符
  • @param Line 行位置,范围:1~2
  • @param Column 列位置,范围:1~16
  • @param Char 要显示的字符
  • @retval 无
    */
    void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
    {
    LCD_SetCursor(Line,Column);
    LCD_WriteData(Char);
    }

/**

  • @brief 在LCD1602指定位置开始显示所给字符串
  • @param Line 起始行位置,范围:1~2
  • @param Column 起始列位置,范围:1~16
  • @param String 要显示的字符串
  • @retval 无
    */
    void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
    {
    unsigned char i;
    LCD_SetCursor(Line,Column);
    for(i=0;String[i]!=’\0’;i++)
    {
    LCD_WriteData(String[i]);
    }
    }

/**

  • @brief 返回值=X的Y次方
    /
    int LCD_Pow(int X,int Y)
    {
    unsigned char i;
    int Result=1;
    for(i=0;i<Y;i++)
    {
    Result
    =X;
    }
    return Result;
    }

/**

  • @brief 在LCD1602指定位置开始显示所给数字
  • @param Line 起始行位置,范围:1~2
  • @param Column 起始列位置,范围:1~16
  • @param Number 要显示的数字,范围:0~65535
  • @param Length 要显示数字的长度,范围:1~5
  • @retval 无
    */
    void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
    {
    unsigned char i;
    LCD_SetCursor(Line,Column);
    for(i=Length;i>0;i–)
    {
    LCD_WriteData(Number/LCD_Pow(10,i-1)%10+‘0’);
    }
    }

/**

  • @brief 在LCD1602指定位置开始以有符号十进制显示所给数字
  • @param Line 起始行位置,范围:1~2
  • @param Column 起始列位置,范围:1~16
  • @param Number 要显示的数字,范围:-32768~32767
  • @param Length 要显示数字的长度,范围:1~5
  • @retval 无
    */
    void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
    {
    unsigned char i;
    unsigned int Number1;
    LCD_SetCursor(Line,Column);
    if(Number>=0)
    {
    LCD_WriteData(’+’);
    Number1=Number;
    }
    else
    {
    LCD_WriteData(’-’);
    Number1=-Number;
    }
    for(i=Length;i>0;i–)
    {
    LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+‘0’);
    }
    }

/**

  • @brief 在LCD1602指定位置开始以十六进制显示所给数字
  • @param Line 起始行位置,范围:1~2
  • @param Column 起始列位置,范围:1~16
  • @param Number 要显示的数字,范围:0~0xFFFF
  • @param Length 要显示数字的长度,范围:1~4
  • @retval 无
    */
    void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
    {
    unsigned char i,SingleNumber;
    LCD_SetCursor(Line,Column);
    for(i=Length;i>0;i–)
    {
    SingleNumber=Number/LCD_Pow(16,i-1)%16;
    if(SingleNumber<10)
    {
    LCD_WriteData(SingleNumber+‘0’);
    }
    else
    {
    LCD_WriteData(SingleNumber-10+‘A’);
    }
    }
    }

/**

  • @brief 在LCD1602指定位置开始以二进制显示所给数字
  • @param Line 起始行位置,范围:1~2
  • @param Column 起始列位置,范围:1~16
  • @param Number 要显示的数字,范围:0~1111 1111 1111 1111
  • @param Length 要显示数字的长度,范围:1~16
  • @retval 无
    */
    void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
    {
    unsigned char i;
    LCD_SetCursor(Line,Column);
    for(i=Length;i>0;i–)
    {
    LCD_WriteData(Number/LCD_Pow(2,i-1)%2+‘0’);
    }
    }

LCD1602.h文件
#ifndef LCD1602_H
#define LCD1602_H

//用户调用函数:
void LCD_Init();
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char);
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String);
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);

#endif

哈哈哈说好的采集电位器信号一不小心把代码放完了

都是代码模块,只要简历对应的文件然后把代码放进去就可以了,如果实在弄不了的可以私信我邮箱或者评论,我看到了会发源文件给你。大家相互帮助哈

至此,所有的代码都已经放出来了,其实这个代码里面包括了。。。天黑亮灯,温度报警。。还有电位器控制LED亮度,,,都在里面,是一个大杂烩。。。。代码很粗糙哈哈哈,也懒得完善了,电位器转动时,舵机跟着转动的动作还是不是很流畅,其实可以做的更细致一点,可以把读取8位变成读取12位,这样动作会细致很多,有兴趣的可以加油试试。

对了,不会舵机接线的可以看程序,我的信号线接在了P10上面

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-11-27 10:04:07  更:2021-11-27 10:05:13 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 10:33:02-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码