其实本人进入芯片的世界的时间并不长,从接触51单片机到现在还不到一年,所以可以算是小白啦,因为制作时间很短,元器件不是很够用,所以只能做出这个只有初级功能的示波器了,只是菜鸟级程序,不建议大家做学习之用。
…
好了,废话不多说,基于stm32 的微型掌上示波器——这个小作品是我几周业余嵌入式技术课的作品。
废话不多说先上实物图:
黑色一个独立按键是增加网格时间间隔的(后来又加了个独立按键减少网格时间间隔);
蓝色按钮是用来暂停波形的,方便观察;
再右边那两个插针是信号输入的GND和SIGNAL端;
三角波
如上图,这个作品使用4.0寸液晶显示屏来做显示的(上图左边),而芯片是用STM32F103C8T6这一款便价STM32来做的(上图右边)。芯片是做好了的最好系统板,在某宝上网购回来的,好像二十多的样子(不算运费)。
如上图,因为院里面的实验室太远,我就自己用51单片机开发板自己做了个简易函数发生器。通过独立按键控制发出正弦波、矩形波、三角波、锯齿波、梯形波。
其实单片机开发板已经是我的核心家当了!因为我学习ARM的时候并没有买ARM的开发板,而是用51开发板把程序烧录进去ARM芯片里面去……(其实零花钱都用去旅游去了。。。)
然后板子使用洞洞板来做的,洞洞板就避免不了飞线,所以我用一块海绵封住背面的飞线,声称是为了防止灰尘干扰电路(其实是为了遮盖惨不忍睹的飞线工艺啦{:12:}{:12:})。
好了就写到这里啦,大家有什么想法或者建议,请给我留言我们一同学习啊
项目参考C语言源代码如下:
/* Includes ------------------------------------------------------------------*/
#include “stm32f10x_lib.h”
/* Private typedef -----------------------------------------------------------/
/ Private define ------------------------------------------------------------*/
#define DAC1_DHR8R1_Address 0x40007408
/* Init Structure definition */
DAC_InitTypeDef DAC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
/* Private macro -------------------------------------------------------------/
/ Private variables ---------------------------------------------------------*/
ErrorStatus HSEStartUpStatus;
uc16 Sine12bit[32] = {2047, 2447, 2831, 3185, 3498, 3750, 3939, 4056, 4095, 4056,
3939, 3750, 3495, 3185, 2831, 2447, 2047, 1647, 1263, 909,
599, 344, 155, 38, 0, 38, 155, 344, 599, 909, 1263, 1647};
u32 DualSine12bit[32];
u8 Idx = 0;
/* Private function prototypes -----------------------------------------------*/
void RCC_Configuration(void);
void GPIO_Configuration(void);
void NVIC_Configuration(void);
void Delay(vu32 nCount);
/* Private functions ---------------------------------------------------------*/
/*******************************************************************************
Function Name : main
Description : Main program.
Input : None
Output : None
Return : None
*******************************************************************************/
int main(void)
{
#ifdef DEBUG
debug();
#endif
/* System Clocks Configuration */
RCC_Configuration();
/* GPIO configuration */
GPIO_Configuration();
/* NVIC Configuration */
NVIC_Configuration();
/* TIM8 Configuration /
/ Time base configuration */
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Period = 0x19;
TIM_TimeBaseStructure.TIM_Prescaler = 0x00;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);
/* TIM8 TRGO selection */
TIM_SelectOutputTrigger(TIM6, TIM_TRGOSource_Update);
/* DAC channel1 Configuration */
DAC_InitStructure.DAC_Trigger = DAC_Trigger_T6_TRGO;
DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;
DAC_Init(DAC_Channel_1, &DAC_InitStructure);
/* DAC channel2 Configuration
DAC_Init(DAC_Channel_2, &DAC_InitStructure); */
/* Fill Sine32bit table */
for (Idx= 0; Idx<32; Idx++)
{
DualSine12bit[Idx] = (Sine12bit[Idx] << 16) + (Sine12bit[Idx]);
}
/* DMA2 channel4 configuration */
DMA_DeInit(DMA1_Channel3); //将dma的通道寄存器设为默认值
DMA_InitStructure.DMA_PeripheralBaseAddr = DAC1_DHR8R1_Address; //定义dma外设基地址
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&DualSine12bit;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //外设作为数据传输的目的地
DMA_InitStructure.DMA_BufferSize = 32; //dma缓存大小
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址寄存器不变
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器 递增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; //外设数据宽度
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //工作在循环缓存模式,数据传输数目为0时,自动恢复配置初值
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //通道未被设置成内存到内存模式,与循环模式相对
DMA_Init(DMA1_Channel3, &DMA_InitStructure); //将DMA_InitStructure中指定的参数初始化dma的通道寄存器
/* Enable DMA2 Channel4 */
DMA_Cmd(DMA1_Channel3, ENABLE); //使能通道
/* Enable DAC Channel1 /
DAC_Cmd(DAC_Channel_1, ENABLE);
/ Enable DAC Channel2 */
DAC_Cmd(DAC_Channel_1, ENABLE);
/* Enable DMA for DAC Channel2 */
DAC_DMACmd(DAC_Channel_1, ENABLE);
/* TIM8 enable counter */
TIM_Cmd(TIM6, ENABLE);
while (1)
{
GPIO_ResetBits(GPIOA , GPIO_Pin_10);
}
}
/*******************************************************************************
Function Name : RCC_Configuration
Description : Configures the different system clocks.
Input : None
Output : None
Return : None
******************************************************************************/
void RCC_Configuration(void)
{
/ RCC system reset(for debug purpose) */
RCC_DeInit();
/* Enable HSE */
RCC_HSEConfig(RCC_HSE_ON);
/* Wait till HSE is ready */
HSEStartUpStatus = RCC_WaitForHSEStartUp();
if(HSEStartUpStatus == SUCCESS)
{
/* Enable Prefetch Buffer */
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
/* Flash 2 wait state */
FLASH_SetLatency(FLASH_Latency_2);
/* HCLK = SYSCLK */
RCC_HCLKConfig(RCC_SYSCLK_Div1);
/* PCLK2 = HCLK */
RCC_PCLK2Config(RCC_HCLK_Div1);
/* PCLK1 = HCLK/2 */
RCC_PCLK1Config(RCC_HCLK_Div2);
/* PLLCLK = 8MHz * 9 = 72 MHz */
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_3);
/* Enable PLL */
RCC_PLLCmd(ENABLE);
/* Wait till PLL is ready */
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
{
}
/* Select PLL as system clock source */
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
/* Wait till PLL is used as system clock source */
while(RCC_GetSYSCLKSource() != 0x08)
{
}
}
/* Enable peripheral clocks --------------------------------------------------/
/ DMA clock enable /
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
/ AFIO and GPIOA Periph clock enable /
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA, ENABLE);
/ DAC Periph clock enable /
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
/ TIM8 Periph clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
}
/*******************************************************************************
Function Name : GPIO_Configuration
Description : Configures the different GPIO ports.
Input : None
Output : None
Return : None
*******************************************************************************/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Configure DAC channe1 and DAC channel2 outputs pins */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5|GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
/*******************************************************************************
/*******************************************************************************
#ifdef DEBUG
/*******************************************************************************
Function Name : assert_failed
Description : Reports the name of the source file and the source line number
where the assert_param error has occurred.
Input : - file: pointer to the source file name
Output : None
Return : None
*****************************************************************************/
void assert_failed(u8 file, u32 line)
{
/ User can add his own implementation to report the file name and line number,
ex: printf(“Wrong parameters value: file %s on line %d\r\n”, file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif
#include"tft3.5.h"
#include “stm32f10x_gpio.h”
//#include"陈锦熙.h"
//#include “美女.h”
//#include “8x16.h”
//#include “GB3231.h”
/------------------------------------------------
清屏函数
------------------------------------------------/
void ClearScreen(unsigned int bColor)
{
unsigned int i,j;
LCD_SetPos(0,320,0,480);//
for (i=0;i<480;i++)
{
for (j=0;j<320;j++)
Write_Data_U16(bColor);
}
}
/-----------------------------------------------------------------------
写8x16点阵格式的字符
-----------------------------------------------------------------------/
#include “8x16.h”
void LCD_PutChar8x16(unsigned short x, unsigned short y, char c, unsigned int fColor, unsigned int bColor)
{
unsigned int i,j;
LCD_SetPos(x,x+8-1,y,y+16-1);
for(i=0; i<16;i++) {
unsigned char m=Font8x16[c*16+i];
for(j=0;j<8;j++) {
if((m&0x80)==0x80) {
Write_Data_U16(fColor);
}
else {
Write_Data_U16(bColor);
}
m<<=1;
}
}
}
/-----------------------------------------------------------------------
写字符
-----------------------------------------------------------------------/
void LCD_PutChar(unsigned short x, unsigned short y, char c, unsigned int fColor, unsigned int bColor) {
LCD_PutChar8x16( x, y, c, fColor, bColor );
}
#include “GB1616.h” //16*16汉字字模
void PutGB1616(unsigned short x, unsigned short y, unsigned char c[2], unsigned int fColor,unsigned int bColor){
unsigned int i,j,k;
LCD_SetPos(x, x+16-1,y, y+16-1);
for (k=0;k<64;k++) { //64标示自建汉字库中的个数,循环查询内码
if ((codeGB_16[k].Index[0]==c[0])&&(codeGB_16[k].Index[1]==c[1])){
for(i=0;i<32;i++) {
unsigned short m=codeGB_16[k].Msk[i];
for(j=0;j<8;j++) {
if((m&0x80)==0x80) {
Write_Data_U16(fColor);
}
else {
Write_Data_U16(bColor);
}
m<<=1;
}
}
}
}
}
/-----------------------------------------------------------------------
写字符串
-----------------------------------------------------------------------/
void LCD_PutString(unsigned short x, unsigned short y, unsigned char *s, unsigned int fColor, unsigned int bColor) {
unsigned char l=0;
while(s) {
if( s < 0x80)
{
LCD_PutChar(x+l8,y,s,fColor,bColor);
s++;l++;
}
else
{
PutGB1616(x+l8,y,(unsigned char)s,fColor,bColor);
s+=2;l+=2;
}
}
}
/-----------------------------------------------------------------------
显示RGB颜色
-----------------------------------------------------------------------/
void Show_RGB (unsigned int x0,unsigned int x1,unsigned int y0,unsigned int y1,unsigned int Color)
{
unsigned int i,j;
LCD_SetPos(x0,x1,y0,y1);
for (i=y0;i<=y1;i++)
{
for (j=x0;j<=x1;j++)
Write_Data_U16(Color);
}
}
/-----------------------------------------------------------------------
显示彩条
-----------------------------------------------------------------------/
void show_colour_bar (void)
{
int V,H;
LCD_SetPos(0,320,0,480);
for(H=0;H<320;H++)
{
for(V=0;V<60;V++)
Write_Data_U16(0xf800);
}
for(H=0;H<320;H++)
{
for(V=60;V<120;V++)
Write_Data_U16(0x07e0);
}
for(H=0;H<320;H++)
{
for(V=120;V<180;V++)
Write_Data_U16(0x001f);
}
for(H=0;H<320;H++)
{
for(V=180;V<240;V++)
Write_Data_U16(0xffe0);
}
for(H=0;H<320;H++)
{
for(V=240;V<300;V++)
Write_Data_U16(0xf81f);
}
for(H=0;H<320;H++)
{
for(V=300;V<360;V++)
Write_Data_U16(0x07ff);
}
for(H=0;H<320;H++)
{
for(V=360;V<420;V++)
Write_Data_U16(0xffff);
}
for(H=0;H<320;H++)
{
for(V=420;V<480;V++)
Write_Data_U16(0x0000);
}
}
/-----------------------------------------------------------------------
写指令 8位总线
-----------------------------------------------------------------------/
void LCD_Write_Command(unsigned char u)
{
TFT_CS_SET(0);
TFT_RS_SET(0);
DATAOUT(u);
TFT_WR_SET(0);
TFT_WR_SET(1);
TFT_CS_SET(1);
}
/-----------------------------------------------------------------------
写数据 8位总线
-----------------------------------------------------------------------/
void LCD_Write_Data(unsigned char u)
{
TFT_CS_SET(0);
TFT_RS_SET(1);
DATAOUT(u);
TFT_WR_SET(0);
TFT_WR_SET(1);
TFT_CS_SET(1);
}
/-----------------------------------------------------------------------
写16位数据
-----------------------------------------------------------------------/
void Write_Data_U16(unsigned int y)
{
unsigned char m,n;
m=y>>8;
n=y;
LCD_Write_Data(m);
LCD_Write_Data(n);
}
/-----------------------------------------------------------------------
延时程序
-----------------------------------------------------------------------/
void delayms(unsigned int count)
{
int i,j;
for(i=0;i
for(j=0;j<26;j++);
}
}
/-----------------------------------------------------------------------
液晶初始化
-----------------------------------------------------------------------/
void ILI9325_Initial(void)
{
// //液晶接口初始化
// RCC->APB2ENR|=0X0000001C;//先使能外设IO PORTA,B,C时钟
//
// GPIOA->CRL=0X33333333; //PA0-7 推挽输出
// //GPIOA->ODR|=0X00FF;//全部输出高
// GPIOB->CRH=0X33333333; //PB8-15 推挽输出
//GPIOB->ODR|=0X00FF;//全部输出高
/*GPIOB->CRL&=0X000FFFFF;//PB5-7 推挽输出
GPIOB->CRL|=0X33300000;
GPIOB->CRH&=0XFFFFFFF0;//PB8 推挽输出
GPIOB->CRH|=0X00000003;
GPIOB->ODR|=0X01E0;//5-8 输出高
GPIOC->CRL&=0XFF00FFFF;//PC4,5 推挽输出
GPIOC->CRL|=0X00330000;
GPIOC->ODR|=0X0030;//4,5 输出高 /
TFT_RST_SET(0);
delayms(20);
TFT_RST_SET(1);
delayms(200);
// VCI=2.80V
//************ Reset LCD Driver ****************//
// Synchronization after reset
LCD_Write_Command(0xFF);
LCD_Write_Command(0xFF);
delayms(5);
LCD_Write_Command(0xFF);
LCD_Write_Command(0xFF);
LCD_Write_Command(0xFF);
LCD_Write_Command(0xFF);
delayms(10);
LCD_Write_Command(0xB0);
LCD_Write_Data(0x00);
LCD_Write_Command(0x11);
delayms(150);
LCD_Write_Command(0xB3);
LCD_Write_Data(0x02);
LCD_Write_Data(0x00);
LCD_Write_Data(0x00);
LCD_Write_Data(0x00);
LCD_Write_Command(0xC0);
LCD_Write_Data(0x13);
LCD_Write_Data(0x3B);//480
LCD_Write_Data(0x00);
LCD_Write_Data(0x02);
LCD_Write_Data(0x00);
LCD_Write_Data(0x01);
LCD_Write_Data(0x00);//NW
LCD_Write_Data(0x43);
LCD_Write_Command(0xC1);
LCD_Write_Data(0x08);
LCD_Write_Data(0x16);//CLOCK
LCD_Write_Data(0x08);
LCD_Write_Data(0x08);
LCD_Write_Command(0xC4);
LCD_Write_Data(0x11);
LCD_Write_Data(0x07);
LCD_Write_Data(0x03);
LCD_Write_Data(0x03);
LCD_Write_Command(0xC6);
LCD_Write_Data(0x00);
LCD_Write_Command(0xC8);//GAMMA
LCD_Write_Data(0x03);
LCD_Write_Data(0x03);
LCD_Write_Data(0x13);
LCD_Write_Data(0x5C);
LCD_Write_Data(0x03);
LCD_Write_Data(0x07);
LCD_Write_Data(0x14);
LCD_Write_Data(0x08);
LCD_Write_Data(0x00);
LCD_Write_Data(0x21);
LCD_Write_Data(0x08);
LCD_Write_Data(0x14);
LCD_Write_Data(0x07);
LCD_Write_Data(0x53);
LCD_Write_Data(0x0C);
LCD_Write_Data(0x13);
LCD_Write_Data(0x03);
LCD_Write_Data(0x03);
LCD_Write_Data(0x21);
LCD_Write_Data(0x00);
LCD_Write_Command(0x35);
LCD_Write_Data(0x00);
LCD_Write_Command(0x36);
LCD_Write_Data(0x00);
LCD_Write_Command(0x3A);
LCD_Write_Data(0x55);
LCD_Write_Command(0x44);
LCD_Write_Data(0x00);
LCD_Write_Data(0x01);
LCD_Write_Command(0xD0);
LCD_Write_Data(0x07);
LCD_Write_Data(0x07);//VCI1
LCD_Write_Data(0x1D);//VRH
LCD_Write_Data(0x03);//BT
LCD_Write_Command(0xD1);
LCD_Write_Data(0x03);
LCD_Write_Data(0x30);//VCM
LCD_Write_Data(0x10);//VDV
LCD_Write_Command(0xD2);
LCD_Write_Data(0x03);
LCD_Write_Data(0x14);
LCD_Write_Data(0x04);
LCD_Write_Command(0x29);
delayms(30);
LCD_Write_Command(0x2A);
LCD_Write_Data(0x00);
LCD_Write_Data(0x00);
LCD_Write_Data(0x01);
LCD_Write_Data(0x3F);//320
LCD_Write_Command(0x2B);
LCD_Write_Data(0x00);
LCD_Write_Data(0x00);
LCD_Write_Data(0x01);
LCD_Write_Data(0xDF);//480
LCD_Write_Command(0xB4);
LCD_Write_Data(0x00);
delayms(100);
LCD_Write_Command(0x2C);
// Write_Cmd_Data(0x0022);//
}
/-----------------------------------------------------------------------
设置坐标点
-----------------------------------------------------------------------/
static void LCD_SetPos(unsigned int x0,unsigned int x1,unsigned int y0,unsigned int y1)
{
LCD_Write_Command(0x2A);
Write_Data_U16(x0);
Write_Data_U16(x1);
//LCD_Write_Data(x0>>8);
//LCD_Write_Data(x0);
//LCD_Write_Data(x1>>8);
//LCD_Write_Data(x1);
LCD_Write_Command(0x2B);
Write_Data_U16(y0);
Write_Data_U16(y1);
//LCD_Write_Data(y0>>8);
//LCD_Write_Data(y0);
//LCD_Write_Data(y1>>8);
//LCD_Write_Data(y1);
LCD_Write_Command(0x2C);
}
//void show_photo(unsigned int x0,unsigned int x1,unsigned int y0,unsigned int y1)
//{
// unsigned int x,y; //定义液晶屏坐标
//
// LCD_SetPos(x0,x1-1,y0,y1-1); //必须x1-1 y1-1
// for(y=y0;y
// LCD_Write_Data(pic[2*((x1-x0)y+x)+1]);
// LCD_Write_Data(pic[2((x1-x0)*y+x)]);
// //Write_Data_U16(0x0f0f);
// } //检测是否写到屏的边缘 160x120 其他尺寸图片请自行更改尺寸
//
//}
void draw_point(unsigned int x0,unsigned int y0,unsigned int wcolor)
{
unsigned int x,y; //定义液晶屏坐标
LCD_SetPos(x0,x0+1,y0,y0+1); //必须x1-1 y1-1
for(y=y0;y
Write_Data_U16(wcolor); //16位颜色
// LCD_Write_Data(pic[2*((x1-x0)y+x)+1]); //每个格子的颜色分开了两个8进制表示
// LCD_Write_Data(pic[2((x1-x0)*y+x)]);
//Write_Data_U16(0x0f0f);
} //检测是否写到屏的边缘 160x120 其他尺寸图片请自行更改尺寸
}
最后,如果有什么意见或者建议欢迎您留言给我,让我们共同学习一起进步,
如果需要 程序完整源代码和 设计文件,请在下方留言或者私信我,看到后会第一时间回复。
谢谢!