当前位置:首页 » 《随便一记》 » 正文

stm32 esp8266 MG90S 机械数码管_碧天鸽哨

6 人参与  2021年11月20日 12:03  分类 : 《随便一记》  评论

点击全文阅读


偶然在b站看到这个项目机械数码管,正好手边有个ESP8266模块还有PCA9685就来做一下。
模型下载地址

目前就搞了一个数字,未来工厂3d打印太贵了
在这里插入图片描述

PCA9685

要先设置频率寄存器才能有输出,想设置频率寄存器必须先把MODE1寄存器的SLEEP位置一。
在这里插入图片描述

void set_freq(float freq)
{
	u16 prescale,oldmode,newmode;
	float prescaleval;
	unsigned int day_time = 0;
	
	freq *= 0.92;   								
	prescaleval = 25000000;						
	prescaleval /= 4096;						//prescaleval=round(osc_cloc/4096/freq)-1;
	prescaleval /= freq;
	prescaleval -= 1;
	prescale = floor(prescaleval + 0.5);		
                
	oldmode = I2C_Read_One_Byte(0x80, PCA9685_MODE1_reg);		  
	newmode = (oldmode&0xEF) | 0x10; 			 
	I2C_Write_One_Byte(0x80, PCA9685_MODE1_reg, newmode);  	  
	I2C_Write_One_Byte(0x80, PCA9685_PRE_SCALE_reg, prescale);   
	I2C_Write_One_Byte(0x80, PCA9685_MODE1_reg, oldmode);
	delay_ms(2);
	I2C_Write_One_Byte(0x80, PCA9685_MODE1_reg, (oldmode | 0xa1));
}	

ESP8266

ESP8266测试

先连接esp8266到电脑,用串口助手发送命令检测模块的功能

#测试模块能否正常工作
AT
#设置模块为sta模式
AT+CWMODE=1
#重启试生效
AT+RST
#连接WiFi
AT+CWJAP="热点名字","密码"
#设置单路模式
AT+CIPMUX=0

时间API

我使用的是淘宝免费的api

#TCP连接
AT+CIPSTART="TCP","api.m.taobao.com",80
#发送71个字符
AT+CIPSEND=71

出现“>”可以发送指令
在这里插入图片描述
输入GET命令,获取时间:

GET http://api.m.taobao.com/rest/api3.do?api=mtop.common.getTimestamp

时间

#透传模式开
AT+CIPMODE=1
#发送数据
AT+CIPSEND

esp8266退出透传模式重新使能AT命令发送“+++”(注意取消串口助手的发送新行)。实际连接单片机使用时出现不断重启的问题,检查后发现应该时模块的供电不够导致的。

串口控制ESP8266

实际使用时发现还是不进入透传模式更方便

char tcp_con[] = "AT+CIPSTART=\"TCP\",\"api.m.taobao.com\",80\r\n";
char send_comm[] = "AT+CIPSEND=71\r\n";
char get_comm[] = "GET http://api.m.taobao.com/rest/api3.do?api=mtop.common.getTimestamp\r\n";

esp8266_init_time();
while(time_flag == NON_OK);
time_flag = NON_OK;

void esp8266_init_time()
{
	esp8266_send(tcp_con);
	delay_ms(100);
	esp8266_send(send_comm);
	delay_ms(100);
	esp8266_send(get_comm);
	delay_ms(100);
}

void esp8266_send(char* str)
{
	uart4_send_str(str);
}

串口4接收返回的时间戳

每次串口接收到新行“\r\n”,接收缓冲区就从头开始接收。根据实际得到的淘宝网返回的字符串格式,发现字符串开头是“+IPD”结尾是“CLOSED”,把这个当作帧头帧尾查找,确定unix时间戳字符所在的位置并将其转化成数值。

u8 day_hour = 0;
u8 day_min = 0;
u8 day_sec = 0;

void UART4_IRQHandler()
{
	u8 res;
	static int index = 0;
	u8 counter = 0;
	unsigned int multi = 1;
	unsigned int day_time = 0;	
	
	if(USART_GetITStatus(UART4, USART_IT_RXNE) != RESET)
	{
		res = USART_ReceiveData(UART4);
		rxbuff[index] = res;
		if((rxbuff[index] == '\n') && (rxbuff[index-1] == '\r'))
		{
			if((rxbuff[index-2] == 'D')&&(rxbuff[index-3] == 'E')&&(rxbuff[index-4] == 'S')&&(rxbuff[index-5] == 'O')&&(rxbuff[index-6] == 'L')&&(rxbuff[index-7] == 'C')&&(rxbuff[0] == '+'))
			{
				unix_time = 0;
				multi = 1;
				for(counter = 0;counter < 10;counter++)
				{
					unix_time += (rxbuff[111-counter] - 0x30) * multi;	
					multi = multi * 10;
				}				
				
				day_time = unix_time % 86400;
				day_hour = day_time / 3600 + 8;
				day_min	 = (day_time % 3600) / 60;
				day_sec  = (day_time % 3600) % 60;
				//day_hour = day_hour + 8;
				//printf("%d:%2d:%2d\r\n", day_hour, day_min, day_sec);
				time_flag = OK;
			}
			index = 0;
		}
		else
		{
			index++;
		}
	}
}

stm32f1串口发送

使用串口发送字符串时,出现了第一个字符发送不出来的情况。
置零sr的tc位:

UART4->SR |= 0xBF;

或者读取一下SR寄存器:

(void)UART4->SR;

定时器每秒钟刷新时间每小时对时一次

#define CHECK_DURATION 3600
void TIM2_IRQHandler(void)   //TIM3??
{
	static u8 flag = 0;
	static unsigned int counter = 0;
	if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)  //??TIM3????????
	{		
		if(counter == CHECK_DURATION)
		{
			esp8266_init();
			//while(time_flag == NON_OK);
			time_flag = NON_OK;
			counter = 0;
			printf("TIME_SYNC\r\n");
		}
		else
		{
			if(day_sec == 59)
			{
				day_sec = 0;
				if(day_min == 59)
				{
					day_min = 0;
					if(day_hour == 23)
					{
						day_hour = 0;
					}
					else
					{
						day_hour++;
					}
				}
				else
				{
					day_min++;
				}
			}
			else
			{
				day_sec++;
			}
			counter++;
		}
		
		if(flag == 0)
		{
			GPIO_ResetBits(GPIOG,GPIO_Pin_13);
			flag = ~flag;
		}
		else
		{
			GPIO_SetBits(GPIOG,GPIO_Pin_13);
			flag = ~flag;
		}		
		printf("%d:%2d:%2d\r\n", day_hour, day_min, day_sec);		
	}
	TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}

如下图可以得到正确的时间:
在这里插入图片描述

字符编码

//				  A			  B			  C 		  D	    	  E			  F			  G
char number[] = {0xcd, 0x00, 0xcd, 0x00, 0x99, 0x01, 0xcd, 0x00, 0x99, 0x01, 0xcd, 0x00, 0xcd, 0x00, 				//0
				 0x99, 0x01, 0x99, 0x01, 0x99, 0x01, 0xcd, 0x00, 0xcd, 0x00, 0xcd, 0x00, 0x99, 0x01, 				//1
				 0xcd, 0x00, 0x99, 0x01, 0x99, 0x01, 0x99, 0x01, 0x99, 0x01, 0x99, 0x01, 0xcd, 0x00, 				//2
				 0xcd, 0x00, 0x99, 0x01, 0x99, 0x01, 0x99, 0x01, 0xcd, 0x00, 0xcd, 0x00, 0xcd, 0x00, 				//3
				 0x99, 0x01, 0xcd, 0x00, 0x99, 0x01, 0x99, 0x01, 0xcd, 0x00, 0xcd, 0x00, 0x99, 0x01, 				//4
				 0xcd, 0x00, 0xcd, 0x00, 0xcd, 0x00, 0x99, 0x01, 0xcd, 0x00, 0xcd, 0x00, 0xcd, 0x00, 				//5
				 0xcd, 0x00, 0xcd, 0x00, 0xcd, 0x00, 0x99, 0x01, 0x99, 0x01, 0xcd, 0x00, 0xcd, 0x00, 				//6
				 0xcd, 0x00, 0x99, 0x01, 0x99, 0x01, 0xcd, 0x00, 0xcd, 0x00, 0xcd, 0x00, 0x99, 0x01, 				//7
				 0xcd, 0x00, 0xcd, 0x00, 0x99, 0x01, 0x99, 0x01, 0x99, 0x01, 0xcd, 0x00, 0xcd, 0x00, 				//8
				 0xcd, 0x00, 0xcd, 0x00, 0x99, 0x01, 0x99, 0x01, 0xcd, 0x00, 0xcd, 0x00, 0xcd, 0x00}; 				//9

//在定时器中断当中调用
void set_num(char num)
{
	//A
	I2C_Write_One_Byte(0x80, PCA9685_CH0_ON_L_reg, 0x00);
	I2C_Write_One_Byte(0x80, PCA9685_CH0_ON_H_reg, 0x00);
	I2C_Write_One_Byte(0x80, PCA9685_CH0_OFF_L_reg, number[num*14]);
	I2C_Write_One_Byte(0x80, PCA9685_CH0_OFF_H_reg, number[num*14+1]);//199-0 cd-1
	//delay_ms(500);
	
	//B
	I2C_Write_One_Byte(0x80, PCA9685_CH1_ON_L_reg, 0x00);
	I2C_Write_One_Byte(0x80, PCA9685_CH1_ON_H_reg, 0x00);
	I2C_Write_One_Byte(0x80, PCA9685_CH1_OFF_L_reg, number[num*14+2]);
	I2C_Write_One_Byte(0x80, PCA9685_CH1_OFF_H_reg, number[num*14+3]);//199-0 cd-1
	//delay_ms(500);
	
	//C
	I2C_Write_One_Byte(0x80, PCA9685_CH2_ON_L_reg, 0x00);
	I2C_Write_One_Byte(0x80, PCA9685_CH2_ON_H_reg, 0x00);
	I2C_Write_One_Byte(0x80, PCA9685_CH2_OFF_L_reg, number[num*14+4]);
	I2C_Write_One_Byte(0x80, PCA9685_CH2_OFF_H_reg, number[num*14+5]);//199-0 cd-1
	//delay_ms(500);
	
	//D
	I2C_Write_One_Byte(0x80, PCA9685_CH3_ON_L_reg, 0x00);
	I2C_Write_One_Byte(0x80, PCA9685_CH3_ON_H_reg, 0x00);
	I2C_Write_One_Byte(0x80, PCA9685_CH3_OFF_L_reg, number[num*14+6]);
	I2C_Write_One_Byte(0x80, PCA9685_CH3_OFF_H_reg, number[num*14+7]);//199-0 cd-1
	//delay_ms(500);
	
	//E
	I2C_Write_One_Byte(0x80, PCA9685_CH4_ON_L_reg, 0x00);
	I2C_Write_One_Byte(0x80, PCA9685_CH4_ON_H_reg, 0x00);
	I2C_Write_One_Byte(0x80, PCA9685_CH4_OFF_L_reg, number[num*14+8]);
	I2C_Write_One_Byte(0x80, PCA9685_CH4_OFF_H_reg, number[num*14+9]);//199-0 cd-1
	//delay_ms(500);
	
	//F
	I2C_Write_One_Byte(0x80, PCA9685_CH5_ON_L_reg, 0x00);
	I2C_Write_One_Byte(0x80, PCA9685_CH5_ON_H_reg, 0x00);
	I2C_Write_One_Byte(0x80, PCA9685_CH5_OFF_L_reg, number[num*14+10]);
	I2C_Write_One_Byte(0x80, PCA9685_CH5_OFF_H_reg, number[num*14+11]);//199-0 cd-1
	//delay_ms(500);
	
	//G
	I2C_Write_One_Byte(0x80, PCA9685_CH6_ON_L_reg, 0x00);
	I2C_Write_One_Byte(0x80, PCA9685_CH6_ON_H_reg, 0x00);
	I2C_Write_One_Byte(0x80, PCA9685_CH6_OFF_L_reg, number[num*14+12]);
	I2C_Write_One_Byte(0x80, PCA9685_CH6_OFF_H_reg, number[num*14+13]);//199-0 cd-1
}

点击全文阅读


本文链接:http://zhangshiyu.com/post/31072.html

串口  发送  寄存器  
<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1