0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于STM32的波形发生器设计

CHANBAEK 来源:单片机资料宝库 作者: 醉生梦死 2023-12-12 15:16 次阅读

一、项目介绍

信号发生器在生产实践和科技领域中有着广泛的应用,各种波形曲线均可以用三角函数方程式来表示。能够产生多种波形,如三角波、锯齿波、矩形波(含方波)、正弦波的电路被称为函数信号发生器。函数信号发生器在电路实验和设备检测中具有十分广泛的用途,例如在通信、广播、电视系统中,都需要射频(高频)发射。这里的射频波就是载波,把音频(低频)、视频信号或脉冲信号运载出去,就需要能够产生高频的振荡器。在工业、农业、生物医学等领域内,如高频感应加热、熔炼、淬火、超声诊断、核磁共振成像等,都需要功率或大或小、频率或高或低的振荡器。函数信号发生器是各种测试和实验过程中不可缺少的工具,在通信、测量、雷达、控制、教学等领域应用十分广泛。不论是在生产、科研还是教学上,信号发生器都是电子工程师信号仿真实验的最佳工具。而且,信号发生器的设计方法多,设计技术也越来越先进, 随着我国经济和科技的发展, 对相应的测试仪器和测试手段也提出了更高的要求,信号发生器己成为测试仪器中至关重要的一类,因此开发信号发生器具有重大意义。

二、主程序流程图

对系统运行工作流程进行说明后,给出系统主程序流程。

设计思路:首先将所有配置进行初始化,为了消除干扰和提升仿真效率,我们将系统的工作状态分为两种,一种为调整状态,另一种为波形输出状态,使用一个开关的通断来调整。

系统主程序流程图如图4-1所示。

图片

三、 Proteus软件仿真调试

正弦波

图片

方波

图片

三角波

图片

锯齿波

图片

四、 硬件调试

在实际电路中,我们可以将频率调整的快一点,但是要注意抗干扰问题,毕竟上面的都是理论值,模拟信号非常容易受到其他因素的干扰。所有配置,都必须跟程序里面完全一致,如果波形失真,或者频率不对,还应进行相对应的补偿。

五、 程序清单

#include "stm32f10x.h"

#include "sys.h"

#include "delay.h"

#include "12864.h"

#include "key4_4.h"

#include "timer.h"

#define KEY0 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10)//读取按键0

void Delay_Ms(u16 time);

/*************** 配置Switch用到的I/O口*******************/

void Init_GPIO_Switch(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);

//关闭jtag,使能SWD,可以用SWD模式调试

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);

// 使能PC端口时钟

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;

//PC0

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

//IO口速度为50MHz

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

//设置成输入

GPIO_Init(GPIOB, &GPIO_InitStructure);

//初始化PC0

}

/****************************************************************

*功能名称:main

*描述:主程序。

*输入:无

*输出:无

*返回:无

****************************************************************/

int main(void)

{

u8 i=0;

RCC_ClocksTypeDef RCC_Clocks; //初始化程序

RCC_Configuration(RCC_PLLMul_4); //8M*4 == 32M

RCC_GetClocksFreq(&RCC_Clocks); //获取片上时钟

Init_12864(); //初始化12864液晶

Key_Init();

Init_GPIO_Switch();

Init_GPIO_DAC0832();

Data0=25;

TIM3_Int_Init(50+Data0,320);

//频率:32000000/ 320 ==100 000 /100 == 1000 /50==20

LCD_P6x8Str(3,16," Sine Wave ");

LCD_P6x8Str(7,6*2,"Frequency: 15 Hz");

while (1)

{

if(KEY0)

{

if(i!=2)

{

__set_PRIMASK(1);

GPIO_ResetBits(GPIOB, ((uint16_t)0xC000));

}

Key_Test();

i=2;

}

else{

if(i!=5)

{

TIM3_Int_Init(50+Data0,320);

__set_PRIMASK(0); //使能TIMx外设

GPIO_ResetBits(GPIOB, ((uint16_t)0xC000));

}

i=5;

}

}

}

/*************** 定时器*******************/

#include "timer.h"

#include "math.h"

#define ADC_CS_WR(a) if (a)

GPIO_SetBits(GPIOB,GPIO_Pin_14);

else

GPIO_ResetBits(GPIOB,GPIO_Pin_14)

#define ADC_CS_WR2(a) if (a)

GPIO_SetBits(GPIOB,GPIO_Pin_15);

else

GPIO_ResetBits(GPIOB,GPIO_Pin_15)

#define PI 3.1415926f //圆周率

u8 mode; //模式:正弦波……

u16 freq; //频率

u8 time; //计次参数

u8 AM; //调幅

/*************** 配置DAC用到的I/O口*******************/

void Init_GPIO_DAC0832(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); // 使能PC端口时钟

GPIO_InitStructure.GPIO_Pin = ((uint16_t)0x03FF); //选择对应的引脚

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz

GPIO_Init(GPIOC, &GPIO_InitStructure); //初始化PC端口

GPIO_SetBits(GPIOC, ((uint16_t)0x00FF)); // 高

GPIO_ResetBits(GPIOC, ((uint16_t)0x00FF)); // 低

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); // 使能PC端口时钟

GPIO_InitStructure.GPIO_Pin = ((uint16_t)0xC000); //选择对应的引脚

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz

GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PC端口

GPIO_SetBits(GPIOC, ((uint16_t)0xC000)); // 高

GPIO_ResetBits(GPIOC, ((uint16_t)0xC000)); // 低

time=0;

ADC_CS_WR(0);

mode=0; //默认输出正弦波

freq=100; //默认频率

AM=255; //最大幅度

}

void DAC_0832_Data(uint8_t Data)

{

GPIO_ResetBits(GPIOC,~Data);

GPIO_SetBits(GPIOC,Data);

}

void sine_wave(u8 location)//输出正弦波

{

double x=(double)location/50*PI;//把0-100放缩到0-2派(pai,没有那个符号)

u8 y=(sin(x)*(AM/2)+(AM/2));//算出y,并放缩到0-254(因为ADC范围0-AM,芯片落后)

DAC_0832_Data(y);

}

void squ_wave(u8 location)//方……

{

if(location<50)

DAC_0832_Data(AM);

else

DAC_0832_Data(0);//这个简单

}

void tri_wave(u8 location)//三……

{

//为了简化,在单周期输出V字形

u8 y;

if(location<50)

y=(50-location)*AM/50;

else

y=(location-50)*AM/50;

DAC_0832_Data(y);

//偶函数,当然说奇函数也没错

}

void saw_wave(u8 location)//锯……

{

DAC_0832_Data(location*AM/100);

//用(100-location)也以变成反向锯齿

}

//通用定时器中断初始化

//这里时钟选择为APB1的2倍,而APB1为36M

//arr:自动重装值。

//psc:时钟预分频数

//这里使用的是定时器3!

void TIM3_Int_Init(u16 arr,u16 psc)

{

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

NVIC_InitTypeDef NVIC_InitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能

TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 计数到5000为500ms

TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 10Khz的计数频率

TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式

TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

TIM_ITConfig( //使能或者失能指定的TIM中断

TIM3, //TIM3

TIM_IT_Update ,

ENABLE //使能

);

// TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);

NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能

NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

TIM_Cmd(TIM3, ENABLE); //使能TIMx外设

// TIM_Cmd(TIM3, DISABLE);

}

void TIM3_IRQHandler(void) //TIM3中断

{

switch(mode)

{

case W_SINE:sine_wave((u8)(time*freq/100)%100);break;//计算出波的位置

case W_SQU:squ_wave((u8)((time*freq/100)%100));break;

case W_TRI:tri_wave((u8)((time*freq/100)%100));break;

case W_SAW:saw_wave((u8)((time*freq/100)%100));break;

}

time++;

if(time>=100)//计数100次

time=0;

}

#include "key4_4.h"

#include "delay.h"

#include "sys.h"

#include "12864.h"

#include "timer.h"

//8个引脚 4个为行 4个为列

//行输出端口定义

#define X1_GPIO_PORT GPIOB

#define X2_GPIO_PORT GPIOB

#define X3_GPIO_PORT GPIOB

#define X4_GPIO_PORT GPIOB

//列输入端口定义

#define Y1_GPIO_PORT GPIOB

#define Y2_GPIO_PORT GPIOB

#define Y3_GPIO_PORT GPIOB

#define Y4_GPIO_PORT GPIOB

//行输出引脚定义

#define X1_GPIO_PIN GPIO_Pin_0

#define X2_GPIO_PIN GPIO_Pin_1

#define X3_GPIO_PIN GPIO_Pin_2

#define X4_GPIO_PIN GPIO_Pin_3

//列输入引脚定义

#define Y1_GPIO_PIN GPIO_Pin_4

#define Y2_GPIO_PIN GPIO_Pin_5

#define Y3_GPIO_PIN GPIO_Pin_6

#define Y4_GPIO_PIN GPIO_Pin_7

//行输出时钟定义

#define X1_RCC RCC_APB2Periph_GPIOB

#define X2_RCC RCC_APB2Periph_GPIOB

#define X3_RCC RCC_APB2Periph_GPIOB

#define X4_RCC RCC_APB2Periph_GPIOB

//列输入时钟定义

#define Y1_RCC RCC_APB2Periph_GPIOB

#define Y2_RCC RCC_APB2Periph_GPIOB

#define Y3_RCC RCC_APB2Periph_GPIOB

#define Y4_RCC RCC_APB2Periph_GPIOB

//移植代码只需要修改上面的端口和引脚和时钟即可,下面的代码不用修改。

//矩阵键盘所用的8个引脚可连续可不连续,看实际需要和个人爱好自己定义。

unsigned char Y1,Y2,Y3,Y4;

void Key_Init(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(X1_RCC|X2_RCC|X3_RCC|X4_RCC|Y1_RCC|Y2_RCC|Y3_RCC|Y4_RCC|RCC_APB2Periph_AFIO, ENABLE);

GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);

/*******************4行输出 *****************************/

GPIO_InitStructure.GPIO_Pin = X1_GPIO_PIN ;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;

GPIO_Init(X1_GPIO_PORT, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = X2_GPIO_PIN ;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;

GPIO_Init(X2_GPIO_PORT, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = X3_GPIO_PIN ;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;

GPIO_Init(X3_GPIO_PORT, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;

GPIO_InitStructure.GPIO_Pin = X4_GPIO_PIN ;

GPIO_Init(X4_GPIO_PORT, &GPIO_InitStructure);

/******************* 4列输入 *******************/

GPIO_InitStructure.GPIO_Pin = Y1_GPIO_PIN ;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;

GPIO_Init(Y1_GPIO_PORT, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = Y2_GPIO_PIN ;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;

GPIO_Init(Y2_GPIO_PORT, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = Y3_GPIO_PIN ;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;

GPIO_Init(Y3_GPIO_PORT, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;

GPIO_InitStructure.GPIO_Pin = Y4_GPIO_PIN;

GPIO_Init(Y4_GPIO_PORT, &GPIO_InitStructure);

}

int Key_Scan(void)

{

uchar KeyVal;

GPIO_SetBits(X1_GPIO_PORT,X1_GPIO_PIN); //先让X1输出高

GPIO_SetBits(X2_GPIO_PORT,X2_GPIO_PIN); //先让X2输出高

GPIO_SetBits(X3_GPIO_PORT,X3_GPIO_PIN); //先让X3输出高

GPIO_SetBits(X4_GPIO_PORT,X4_GPIO_PIN); //先让X4输出高

if((GPIO_ReadInputDataBit(Y1_GPIO_PORT,Y1_GPIO_PIN)|GPIO_ReadInputDataBit(Y2_GPIO_PORT,Y2_GPIO_PIN)|GPIO_ReadInputDataBit(Y3_GPIO_PORT,Y3_GPIO_PIN)|GPIO_ReadInputDataBit(Y4_GPIO_PORT,Y4_GPIO_PIN))==0x0000)

return -1; //如果X1到X4全为零则没有按键按下

else

{

Delay_Ms(5); //延时5ms去抖动

if((GPIO_ReadInputDataBit(Y1_GPIO_PORT,Y1_GPIO_PIN)|GPIO_ReadInputDataBit(Y2_GPIO_PORT,Y2_GPIO_PIN)|GPIO_ReadInputDataBit(Y3_GPIO_PORT,Y3_GPIO_PIN)|GPIO_ReadInputDataBit(Y4_GPIO_PORT,Y4_GPIO_PIN))==0x0000)

return -1;

}

GPIO_ResetBits(X1_GPIO_PORT,X1_GPIO_PIN);

GPIO_ResetBits(X2_GPIO_PORT,X2_GPIO_PIN);

GPIO_ResetBits(X3_GPIO_PORT,X3_GPIO_PIN);

GPIO_SetBits(X4_GPIO_PORT,X4_GPIO_PIN);

Y1=GPIO_ReadInputDataBit(Y1_GPIO_PORT,Y1_GPIO_PIN);Y2=GPIO_ReadInputDataBit(Y2_GPIO_PORT,Y2_GPIO_PIN);

Y3=GPIO_ReadInputDataBit(Y3_GPIO_PORT,Y3_GPIO_PIN);Y4=GPIO_ReadInputDataBit(Y4_GPIO_PORT,Y4_GPIO_PIN);

if(Y1==1&&Y2==0&&Y3==0&&Y4==0)

KeyVal='*';

if(Y1==0&&Y2==1&&Y3==0&&Y4==0)

KeyVal=0;

if(Y1==0&&Y2==0&&Y3==0&&Y4==1)

KeyVal='D';

if(Y1==0&&Y2==0&&Y3==1&&Y4==0)

KeyVal='#';

while(((GPIO_ReadInputDataBit(Y1_GPIO_PORT,Y1_GPIO_PIN))|(GPIO_ReadInputDataBit(Y2_GPIO_PORT,Y2_GPIO_PIN))|(GPIO_ReadInputDataBit(Y3_GPIO_PORT,Y3_GPIO_PIN))|(GPIO_ReadInputDataBit(Y4_GPIO_PORT,Y4_GPIO_PIN))) > 0);

//等待按键释放

GPIO_SetBits(X1_GPIO_PORT,X1_GPIO_PIN);

GPIO_ResetBits(X2_GPIO_PORT,X2_GPIO_PIN);

GPIO_ResetBits(X3_GPIO_PORT,X3_GPIO_PIN);

GPIO_ResetBits(X4_GPIO_PORT,X4_GPIO_PIN);

Y1=GPIO_ReadInputDataBit(Y1_GPIO_PORT,Y1_GPIO_PIN);Y2=GPIO_ReadInputDataBit(Y2_GPIO_PORT,Y2_GPIO_PIN);

Y3=GPIO_ReadInputDataBit(Y3_GPIO_PORT,Y3_GPIO_PIN);Y4=GPIO_ReadInputDataBit(Y4_GPIO_PORT,Y4_GPIO_PIN);

if(Y1==1&&Y2==0&&Y3==0&&Y4==0)

KeyVal=1;

if(Y1==0&&Y2==1&&Y3==0&&Y4==0)

KeyVal=2;

if(Y1==0&&Y2==0&&Y3==1&&Y4==0)

KeyVal=3;

if(Y1==0&&Y2==0&&Y3==0&&Y4==1)

KeyVal='A';

while(((GPIO_ReadInputDataBit(Y1_GPIO_PORT,Y1_GPIO_PIN))|(GPIO_ReadInputDataBit(Y2_GPIO_PORT,Y2_GPIO_PIN))|(GPIO_ReadInputDataBit(Y3_GPIO_PORT,Y3_GPIO_PIN))|(GPIO_ReadInputDataBit(Y4_GPIO_PORT,Y4_GPIO_PIN))) > 0);

GPIO_ResetBits(X1_GPIO_PORT,X1_GPIO_PIN);

GPIO_SetBits(X2_GPIO_PORT,X2_GPIO_PIN);

GPIO_ResetBits(X3_GPIO_PORT,X3_GPIO_PIN);

GPIO_ResetBits(X4_GPIO_PORT,X4_GPIO_PIN);

Y1=GPIO_ReadInputDataBit(Y1_GPIO_PORT,Y1_GPIO_PIN);Y2=GPIO_ReadInputDataBit(Y2_GPIO_PORT,Y2_GPIO_PIN);

Y3=GPIO_ReadInputDataBit(Y3_GPIO_PORT,Y3_GPIO_PIN);Y4=GPIO_ReadInputDataBit(Y4_GPIO_PORT,Y4_GPIO_PIN);

if(Y1==1&&Y2==0&&Y3==0&&Y4==0)

KeyVal=4;

if(Y1==0&&Y2==1&&Y3==0&&Y4==0)

KeyVal=5;

if(Y1==0&&Y2==0&&Y3==1&&Y4==0)

KeyVal=6;

if(Y1==0&&Y2==0&&Y3==0&&Y4==1)

KeyVal='B';

while(((GPIO_ReadInputDataBit(Y1_GPIO_PORT,Y1_GPIO_PIN))|(GPIO_ReadInputDataBit(Y2_GPIO_PORT,Y2_GPIO_PIN))|(GPIO_ReadInputDataBit(Y3_GPIO_PORT,Y3_GPIO_PIN))|(GPIO_ReadInputDataBit(Y4_GPIO_PORT,Y4_GPIO_PIN))) > 0);

GPIO_ResetBits(X1_GPIO_PORT,X1_GPIO_PIN);

GPIO_ResetBits(X2_GPIO_PORT,X2_GPIO_PIN);

GPIO_SetBits(X3_GPIO_PORT,X3_GPIO_PIN);

GPIO_ResetBits(X4_GPIO_PORT,X4_GPIO_PIN);

Y1=GPIO_ReadInputDataBit(Y1_GPIO_PORT,Y1_GPIO_PIN);Y2=GPIO_ReadInputDataBit(Y2_GPIO_PORT,Y2_GPIO_PIN);

Y3=GPIO_ReadInputDataBit(Y3_GPIO_PORT,Y3_GPIO_PIN);Y4=GPIO_ReadInputDataBit(Y4_GPIO_PORT,Y4_GPIO_PIN);

if(Y1==1&&Y2==0&&Y3==0&&Y4==0)

KeyVal=7;

if(Y1==0&&Y2==1&&Y3==0&&Y4==0)

KeyVal=8;

if(Y1==0&&Y2==0&&Y3==1&&Y4==0)

KeyVal=9;

if(Y1==0&&Y2==0&&Y3==0&&Y4==1)

KeyVal='C';

while(((GPIO_ReadInputDataBit(Y1_GPIO_PORT,Y1_GPIO_PIN))|(GPIO_ReadInputDataBit(Y2_GPIO_PORT,Y2_GPIO_PIN))|(GPIO_ReadInputDataBit(Y3_GPIO_PORT,Y3_GPIO_PIN))|(GPIO_ReadInputDataBit(Y4_GPIO_PORT,Y4_GPIO_PIN))) > 0);

return KeyVal;

}

/************************************

按键表盘为: 1 2 3 A

4 5 6 B

7 8 9 C

  • 0 # D

************************************/

u8 ee,Data0=0;

void Key_Test(void)

{

int num;

char Freq[3]={'�'};

num = Key_Scan();

if(ee!=num)

switch(num)

{

case 0: LCD_P6x8Str(1,1,"0"); break;

case 1: LCD_P6x8Str(1,1,"1"); break;

case 2: LCD_P6x8Str(1,1,"2"); break;

case 3: LCD_P6x8Str(1,1,"3"); break;

case 4: LCD_P6x8Str(1,1,"4"); break;

case 5: LCD_P6x8Str(1,1,"5"); break;

case 6: LCD_P6x8Str(1,1,"6"); break;

case 7: LCD_P6x8Str(1,1,"7"); break;

case 8: LCD_P6x8Str(1,1,"8"); break;

case 9: LCD_P6x8Str(1,1,"9"); break;//

case'A':LCD_P6x8Str(1,1,"A");

mode=0;LCD_P6x8Str(3,16," Sine Wave "); break;

case'B':LCD_P6x8Str(1,1,"B");

mode=1;LCD_P6x8Str(3,16," Square wave "); break;

case'C':LCD_P6x8Str(1,1,"C"); mode=2;LCD_P6x8Str(3,16,"Ttiangular wave"); break;

case 'D': LCD_P6x8Str(1,1,"D");

mode=3;LCD_P6x8Str(3,16," Sawtooth Wave ");

break;

case '#': LCD_P6x8Str(1,1,"#");

if(Data0>=5)Data0-=5;

Freq[0]=(20-Data0/5)/10+'0';

Freq[1]=(20-Data0/5)%10+'0';

LCD_P6x8Str(7,6*13,Freq);

break;

case ' ': LCD_P6x8Str(1,1," ");

if(Data0<50)Data0+=5; Freq[0]=(20-Data0/5)/10+'0';

Freq[1]=(20-Data0/5)%10+'0';

LCD_P6x8Str(7,6*13,Freq);

break;

}

ee=num;

}

//*************************************

12864

//*************************************

//*************************************

//写数据地址

//*************************************

void write_12864com(uint8_t com)

{

uint8_t temp = 0x01;

uint8_t k[8] = {0};

uint8_t i;

Check_status();

for(i=0; i<8; i++)

{

if(com & temp)

k[i] = 1;

else

k[i] = 0;

temp=temp << 1;

}

temp = 0x01;

RS=0;

RW=0;

D0=k[0];

D1=k[1];

D2=k[2];

D3=k[3];

D4=k[4];

D5=k[5];

D6=k[6];

D7=k[7];

En=1;

Delay_Ms(1);

En=0;

Delay_Ms(1);

}

//*************************************

//写数据

//*************************************

void write_12864data(uint8_t dat)

{

uint8_t temp = 0x01;

uint8_t k[8] = {0};

uint8_t i;

Check_status();//延时检查很重要,在连续刷新的时候

for(i=0; i<8; i++)

{

if(dat & temp)

k[i] = 1;

else

k[i] = 0;

temp=temp << 1;

}

temp = 0x01;

RS=1;

RW=0;

D0=k[0];

D1=k[1];

D2=k[2];

D3=k[3];

D4=k[4];

D5=k[5];

D6=k[6];

D7=k[7];

En=1;//在使能信号的下降沿写入了数据

Delay_Ms(1);

En=0;

Delay_Ms(1);

}

uint8_t read_12864data()

{

//这个函数的代码测试未通过

uint8_t temp = 0;

uint8_t k[8] = {0};

uint8_t i;

Check_status();

RS=1;

RW=1;

En=1;//使能端高电平读取数据

Delay_Ms(1);

LCD12864_DataRead_PortInit();//端口方向改为输入

k[0]=DI0;

k[1]=DI1;

k[2]=DI2;

k[3]=DI3;

k[4]=DI4;

k[5]=DI5;

k[6]=DI6;

k[7]=DI7;

LCD12864_DataWrite_PortInit();//端口方向改为输出

for (i=0; i<8; i++)

{

temp |= ((k[i]&0x01)<

}

return temp;

}

void LCD_Set_Pos(uint8_t page,uint8_t x)//LCD当前光标设置,先选页,后选横向起始坐标

{

uint8_t Column=0;

(x>127)?(x=127):(x=x);

(x<1)?(x=0):(x=x);

if (page>8)

{

page=8;

}

else if (page<1)

{

page=1;

}

page=page-1;

if (x<=63)

{ LCDSelectScreen(LeftScreen);

LCDSetPage(page);

Column=x;

LCDSetColumn(Column);

}

else if (x>63)

{ LCDSelectScreen(RightScreen);

LCDSetPage(page);

Column = x-64;

LCDSetColumn(Column);

// if (Column == 0)

// { //如果第一次进入右半屏,需要空写一次,在设置一次,方可

// write_12864data(0x00);

// }

LCDSelectScreen(RightScreen);//上面的判断不对,应该是写两次命令就会解决右半屏首字下沉那个问题

LCDSetPage(page);

Column = x-64;

LCDSetColumn(Column);

}

}

void LCD_P6x8Str(uint8_t x, uint8_t y, char ch[])

{

uint8_t c = 0, i = 0, j = 0;

while (ch[j] != '�')

{

c = ch[j]-32;

for (i = 0; i < 6; i++)

{ LCD_Set_Pos(x, y);//因为这个AMPIRE 分为左右半屏,所以光标设置必须写在这里,确保每个字符是完整的

write_12864data(F6x8[c][i]);

y = y+1;

}

j++;

}

}

void LCD_DispACat(unsigned char x, unsigned char y)

{

unsigned char i = 0, j = 0;

if (x > 4)

{

x = 4;

y++;

}

x=x-1;

for (j = 0; j < 4; j++)

{

LCD_Set_Pos(x, y);

x++;

for (i = 0; i < 32; i++)

write_12864data(LCD_cat[i + j * 32]);

}

}

//********************************************************

//12864初始化

//********************************************************

void Init_12864()

{

//端口初始化

RCC->APB2ENR|=1<<2; //使能PORTA时钟

GPIOA->CRH&=0X00000000;

GPIOA->CRH|=0X44333333;//PA8~13推挽输出,PA14,15浮空输入,因为这个型号的LCD要检测内部是否忙

GPIOA->ODR|=0X00FFFFFF;//PA8~13输出高

LCD12864_DataWrite_PortInit();

Reset=0;

Delay_Ms(1);

Reset=1;

Check_status();

LCDSelectScreen(AllScreen);//屏幕选择全屏

LCDSetOnOff(Off);

LCDSelectScreen(AllScreen);//屏幕选择全屏

LCDSetOnOff(On);

LCDSelectScreen(AllScreen);//屏幕选择全屏

LCDClearScreen(AllScreen);//清屏

LCDSetLine(0);

}

void LCD12864_DataWrite_PortInit()

{

RCC->APB2ENR|=1<<2;

GPIOA->CRL&=0X00000000; //PORTA低八位为数据位,推挽输出,写数据用

GPIOA->CRL|=0X33333333;

GPIOA->ODR|=0XFFFFFFFF;

}

void LCD12864_DataRead_PortInit()

{

RCC->APB2ENR|=1<<2;

GPIOA->CRL&=0X00000000; //PORTA低八位为数据位,浮空输入,读数据用

GPIOA->CRL|=0X44444444;

//GPIOA->ODR|=0XFFFFFFFF;

}

void LCDSelectScreen(ScreenTypedef screen)

{

switch(screen)

{

case AllScreen:

CS1=0;

CS2=0;

break;

case LeftScreen:

CS1=0;

CS2=1;

break;

case RightScreen:

CS1=1;

CS2=0;

break;

default :

break;

}

}

void LCDSetOnOff(LCDSetOnOffTypedef Status)

{

switch (Status)

{

case On:

write_12864com(0x3e+1);

break;

case Off:

write_12864com(0x3e);

break;

default:

break;

}

}

void LCDClearScreen(ScreenTypedef screen)

{

uint8_t i,j;

LCDSelectScreen(screen);

for (i=0; i<=7; i++)

{

LCDSetPage(i);

LCDSetColumn(0);

for(j=0; j<=63; j++)

{

write_12864data(0x00);//写完后地址自动加一

}

}

}

void LCDSetPage(uint8_t Page)

{

Page=0xb8|Page;

write_12864com(Page);

}

void LCDSetLine(uint8_t Line)

{

Line=0xc0|Line;

write_12864com(Line);

}

void LCDSetColumn(uint8_t Colnum)

{

Colnum=Colnum&0x3f;

Colnum=Colnum|0x40;

write_12864com(Colnum);

}

void Check_status()

{

D0=0;

D1=0;

D2=0;

D3=0;

D4=0;

D5=0;

D6=0;

D7=0;

RS=0;

RW=1;

//En=1;

// while(CheckPin == 0);//不启用忙检测

Delay_Ms(2);

//En=0;

}

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 正弦波
    +关注

    关注

    11

    文章

    635

    浏览量

    55250
  • STM32
    +关注

    关注

    2265

    文章

    10870

    浏览量

    354692
  • 信号发生器
    +关注

    关注

    28

    文章

    1452

    浏览量

    108643
  • 波形发生器
    +关注

    关注

    3

    文章

    288

    浏览量

    31352
收藏 人收藏

    评论

    相关推荐

    基于stm32波形发生器设计

    #include “dac.h”//DAC 通道 1 输出初始化void Dac1_Init(void){GPIO_InitTypeDef GPIO_InitStructure;DAC_InitTypeDef DAC_InitType;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE ); //①使能 PA 时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE ); //②使能DAC时钟G
    发表于 08-16 08:39

    如何去实现一种基于stm32波形发生器

    如何去实现一种基于stm32波形发生器呢?其代码程序该怎样去实现呢?
    发表于 11-17 06:19

    怎么实现基于STM32波形发生器的设计?

    怎么实现基于STM32波形发生器的设计?
    发表于 11-26 06:16

    程序波形发生器电路

    程序波形发生器电路 程序波形发生器
    发表于 02-09 16:07 972次阅读
    程序<b class='flag-5'>波形</b><b class='flag-5'>发生器</b>电路

    SPWM波形发生器设计与应用

    SPWM波形发生器设计与应用
    发表于 07-24 16:11 5954次阅读
    SPWM<b class='flag-5'>波形</b><b class='flag-5'>发生器</b>设计与应用

    波形发生器设计简述

    在工作中,我们常常会用到波形发生器,它是使用频度很高的电子仪器。现在的波形发生器都采用单片机来构成。单片机波形
    发表于 03-28 15:43 0次下载

    波形发生器

    波形发生器,可以生成4中波形。正玄波,矩形波,三角波等。
    发表于 05-13 10:17 30次下载

    波形发生器的设计

    波形发生器的设计
    发表于 12-17 21:49 30次下载

    简易波形发生器

    简易波形发生器
    发表于 01-05 14:34 29次下载

    波形发生器

    多种波形发生器课程设计。
    发表于 02-08 02:37 180次下载

    波形发生器应用的测量

    波形发生器应用的测量
    发表于 03-28 10:24 1次下载

    关于波形发生器的设计

    波形发生器
    发表于 07-03 15:31 120次下载

    iboard教程之基于STM32波形发生器的软件分析

    发表于 10-29 09:22 0次下载
    iboard教程之基于<b class='flag-5'>STM32</b>的<b class='flag-5'>波形</b><b class='flag-5'>发生器</b>的软件分析

    关于波形发生器,你知道多少?

    信号发生器系列波形发生器你知道多少?虹科信号发生器系列波形发生器
    的头像 发表于 08-05 08:07 2905次阅读
    关于<b class='flag-5'>波形</b><b class='flag-5'>发生器</b>,你知道多少?

    什么是任意波形发生器

    在电子测量、通信、科研以及音乐创作等多个领域中,波形发生器作为一种能够产生特定波形信号的电子设备,发挥着不可或缺的作用。而任意波形发生器(A
    的头像 发表于 05-30 15:53 870次阅读