详细资源包下载:点击此处
一、GPIO的输出
1.时钟设置
2.调用初始化函数
3.输出函数
(1)GPIO_WriteBit(端口,引脚,(BitAction)(0));//低
GPIO_WriteBit(端口,引脚,(BitAction)(1));//高
(2)GPIO_SetBits(端口,引脚); //低
GPIO_ResetBits端口,引脚); //高
(3)PAout(n) = 1:PAn;//输出高
PAout(n) = 0;//输出低
P端口out(引脚) = 0|1
(4)PAin(n) = 1;//输入高
PAin(n) = 0;//输入低
P端口in(引脚) = 0|1
void Init(void){ //初始化
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//参数一:GPIOB口输出,参数二:使能
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;//B0和B1
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //输出频率
GPIO_Init(LEDPORT, &GPIO_InitStructure);//初始化
}
用途
例一:
点亮led
步骤:
1.初始化时钟
2.初始化PB0,1
3.调用GPIO输出函数
连接方式:
位数码管连接3.3v
段数码管连接PB0
#define LEDPORT GPIOB
#define LED1 GPIO_Pin_0
#define LED2 GPIO_Pin_1
void LED_Init(void){
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Pin = LED1 | LED2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(LEDPORT, &GPIO_InitStructure);
}
int Led1(){
RCC_Configuration();
LED_Init();
while(1){
GPIO_WriteBit(LEDPORT,LED1,(BitAction)(0));//低电平亮,高电平灭
delay_ms(100);
GPIO_WriteBit(LEDPORT,LED1,(BitAction)(1));
delay_ms(100);
}
}
按键控制Led
步骤:
1.初始化按键
2.获取按键电平
GPIO_ReadInputDataBit(KEYPORT1,KEY1)
按下返回低电平0,松开返回高电平1
连接方式:
无
//按键1 C13
#define KEYPORT1 GPIOC
#define KEY1 GPIO_Pin_13
//按键2 D13
#define KEYPORT2 GPIOD
#define KEY2 GPIO_Pin_13
void KEY1_Init(void){
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
GPIO_InitStructure.GPIO_Pin = KEY1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
// GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(KEYPORT1,&GPIO_InitStructure);
}
void KEY2_Init(void){
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);
GPIO_InitStructure.GPIO_Pin = KEY2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
// GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(KEYPORT2,&GPIO_InitStructure);
}
例二:蜂鸣器
步骤:
1.初始化时钟
2.初始化PB5
3.调用GPIO输出函数
连接方式:
无
#define BUZZERPORT GPIOB
#define BUZZER GPIO_Pin_5
void BUZZER_Init(void){
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = BUZZER;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(BUZZERPORT, &GPIO_InitStructure);
GPIO_WriteBit(BUZZERPORT,BUZZER,(BitAction)(1));
}
void BUZZER_BEEP1(void){
u16 i;
for(i=0;i<200;i++){
GPIO_WriteBit(BUZZERPORT,BUZZER,(BitAction)(0));
delay_us(500);
GPIO_WriteBit(BUZZERPORT,BUZZER,(BitAction)(1));
delay_us(500);
}
}
例三:点亮动态数码管
步骤:
1.初始化时钟
2.初始化PB0,1,2,3,4,5,6,7
3.调用GPIO输出函数
连接方式:
数码管段选输出口为PA0-7,位选输出口为PB10-13 PC6-9
void GPIO_Configuration(void)//时钟配置子程序
{
GPIO_InitTypeDef GPIO_InitStructure;//声明GPIO初始化结构变量
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_7|GPIO_Pin_6|GPIO_Pin_5|GPIO_Pin_4|GPIO_Pin_3|GPIO_Pin_2|GPIO_Pin_1|GPIO_Pin_0;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_InitStructure.GPIO_Pin);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13;
GPIO_Init(GPIOB,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9|GPIO_Pin_8|GPIO_Pin_7|GPIO_Pin_6;
GPIO_Init(GPIOC,&GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_InitStructure.GPIO_Pin);
}
void Show_Num(double num){
double num1 = num;
unsigned char index = 0;
unsigned int n = 1;
unsigned int num2;
unsigned char i;
while((unsigned int)num1 != num1&&index < 4){
index++;
num1 = num1*10;
n = n*10;
}
num2 = num1;
LedOut[0]=Disp_Tab[num2/10000000%10];
LedOut[1]=Disp_Tab[num2/1000000%10];
LedOut[2]=Disp_Tab[num2/100000%10];
LedOut[3]=Disp_Tab[num2/10000%10];
LedOut[4]=Disp_Tab[num2/1000%10];
LedOut[5]=Disp_Tab[num2/100%10];
LedOut[6]=Disp_Tab[num2/10%10];
LedOut[7]=Disp_Tab[num2%10];
LedOut[7-index]=Disp_Tab1[num2/n%10];
for(i=0; i<8; i++)
{
GPIO_Write(GPIOA , LedOut[i]) ;
LED1(0);LED2(0);LED3(0);LED4(0);LED5(0);LED6(0);LED7(0);LED8(0);
switch(i)
{
case 0:
LED1(1);LED2(0);LED3(0);LED4(0);LED5(0);LED6(0);LED7(0);LED8(0);
break;
case 1:
LED1(0);LED2(1);LED3(0);LED4(0);LED5(0);LED6(0);LED7(0);LED8(0);
break;
case 2:
LED1(0);LED2(0);LED3(1);LED4(0);LED5(0);LED6(0);LED7(0);LED8(0);
break;
case 3:
LED1(0);LED2(0);LED3(0);LED4(1);LED5(0);LED6(0);LED7(0);LED8(0);
break;
case 4:
LED1(0);LED2(0);LED3(0);LED4(0);LED5(1);LED6(0);LED7(0);LED8(0);
break;
case 5:
LED1(0);LED2(0);LED3(0);LED4(0);LED5(0);LED6(1);LED7(0);LED8(0);
break;
case 6:
LED1(0);LED2(0);LED3(0);LED4(0);LED5(0);LED6(0);LED7(1);LED8(0);
break;
case 7:
LED1(0);LED2(0);LED3(0);LED4(0);LED5(0);LED6(0);LED7(0);LED8(1);
break;
}
delay_nms(1);
}
}
#include "stm32f10x.h" // Device header
#include "dynamic_seg_led.h"
int main(void)
{
RCC_Configuration1();//配置时钟
GPIO_Configuration();//配置GPIO口
LED1(0);LED2(0);LED3(0);LED4(0);LED5(0);LED6(0);LED7(0);LED8(0);//熄灭所有数码管
while(1){
Show_Num(1234.5678);//显示想显示的数
}
}
例四: 驱动灯泡,风扇,门锁
步骤:
与例一相同
线路连接:
GPIO输出口连接继电器J2(J5),J9(J12)连接设备正极,J8(J11)连接电源正极12V,设备负极连接电源负极
例五: 键盘模块
步骤:
1.时钟设置
2.44或55键盘初始化
3.获取按键信息,如将获取的信息显示在数码管上
连线:
4*4键盘
COL0-COL3 PB10-PB13
ROW0-ROW3 PC6-PC9
5*5键盘
ROW0-ROW4 PA0-PA4
COL4-COL0 PB14-PB10
//键盘初始化
void GPIO_Configuration55(void)
{
GPIO_InitTypeDef GPIO_InitStructure;//声明GPIO初始化结构变量
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启PA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //开启PB时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); //开启PC时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_3|GPIO_Pin_2|GPIO_Pin_1|GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //配置成推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //输出速度 50M HZ
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA口
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //
GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PB口
GPIO_Write(GPIOB, 0x7C00); //上拉输入需要把对应的ODR置1
}
/*
5*5矩阵按键设置
*/
int keyscan55(void)
{
ROW14(0);ROW13(0);ROW12(0);ROW11(0);ROW10(0);//ÐÐÏßÀµÍ
// | | | | |
// 0 PA0 ---0-----1-----2-----3-----4-- | |--------|
// | | | | | --------
// 0 PA1 ---5-----6-----7-----8-----9--
// | | | | |
// 0 PA2 ---A-----B-----C-----D-----E--
// | | | | |
// 0 PA3 ---F-----H-----I-----J-----K--
// | | | | |
// 0 PA4 ---L-----M-----N-----O-----P--
// | | | | |
// PB14 PB13 PB12 PB11 PB10
//
if(COL14&&COL13&&COL12&&COL11&&COL10){
return -1;
}
else
{
delay_nms(5);
if(COL14&&COL13&&COL12&&COL11&&COL10)
return -1;
}
// | | | | |
// 0 PA0 ---0-----1-----2-----3-----4-- | |--------|
// | | | | | --------
// 1 PA1 ---5-----6-----7-----8-----9--
// | | | | |
// 1 PA2 ---A-----B-----C-----D-----E--
// | | | | |
// 1 PA3 ---F-----H-----I-----J-----K--
// | | | | |
// 1 PA4 ---L-----M-----N-----O-----P--
// | | | | |
// PB14 PB13 PB12 PB11 PB10
//
ROW14(1);ROW13(1);ROW12(1);ROW11(1);ROW10(0);
if(!COL14){
return 0;
}
if(!COL13){
return 1;
}
if(!COL12){
return 2;
}
if(!COL11){
return 3;
}
if(!COL10){
return 4;
}
// | | | | |
// 1 PA0 ---0-----1-----2-----3-----4-- | |--------|
// | | | | | --------
// 0 PA1 ---5-----6-----7-----8-----9--
// | | | | |
// 1 PA2 ---A-----B-----C-----D-----E--
// | | | | |
// 1 PA3 ---F-----H-----I-----J-----K--
// | | | | |
// 1 PA4 ---L-----M-----N-----O-----P--
// | | | | |
// PB14 PB13 PB12 PB11 PB10
//
ROW14(1);ROW13(1);ROW12(1);ROW11(0);ROW10(1);
if(!COL14){
return 5;
}
if(!COL13){
return 6;
}
if(!COL12){
return 7;
}
if(!COL11){
return 8;
}
if(!COL10){
return 9;
}
// | | | | |
// 1 PA0 ---0-----1-----2-----3-----4-- | |--------|
// | | | | | --------
// 1 PA1 ---5-----6-----7-----8-----9--
// | | | | |
// 0 PA2 ---A-----B-----C-----D-----E--
// | | | | |
// 1 PA3 ---F-----H-----I-----J-----K--
// | | | | |
// 1 PA4 ---L-----M-----N-----O-----P--
// | | | | |
// PB14 PB13 PB12 PB11 PB10
//
ROW14(1);ROW13(1);ROW12(0);ROW11(1);ROW10(1);
if(!COL14){
return 10;
}
if(!COL13){
return 11;
}
if(!COL12){
return 12;
}
if(!COL11){
return 13;
}
if(!COL10){
return 14;
}
// | | | | |
// 1 PA0 ---0-----1-----2-----3-----4-- | |--------|
// | | | | | --------
// 1 PA1 ---5-----6-----7-----8-----9--
// | | | | |
// 1 PA2 ---A-----B-----C-----D-----E--
// | | | | |
// 0 PA3 ---F-----H-----I-----J-----K--
// | | | | |
// 1 PA4 ---L-----M-----N-----O-----P--
// | | | | |
// PB14 PB13 PB12 PB11 PB10
//
ROW14(1);ROW13(0);ROW12(1);ROW11(1);ROW10(1);
if(!COL14){
return 15;
}
if(!COL13){
return 16;
}
if(!COL12){
return 17;
}
if(!COL11){
return 18;
}
if(!COL10){
return 19;
}
// | | | | |
// 1 PA0 ---0-----1-----2-----3-----4-- | |--------|
// | | | | | --------
// 1 PA1 ---5-----6-----7-----8-----9--
// | | | | |
// 1 PA2 ---A-----B-----C-----D-----E--
// | | | | |
// 1 PA3 ---F-----H-----I-----J-----K--
// | | | | |
// 0 PA4 ---L-----M-----N-----O-----P--
// | | | | |
// PB14 PB13 PB12 PB11 PB10
//
ROW14(0);ROW13(1);ROW12(1);ROW11(1);ROW10(1);
if(!COL14){
return 20;
}
if(!COL13){
return 21;
}
if(!COL12){
return 22;
}
if(!COL11){
return 23;
}
if(!COL10){
return 24;
}
return -1;
}
void delay_nms(u16 time)//ÑÓʱ×Ó³ÌÐò
{ u16 i=0;
while(time--)
{ i=12000; //×Ô¼º¶¨Òå
while(i--) ;
}
}
#include "stm32f10x.h" //STM32
#include "matrix_key.h"
#include "usart.h"
// 此表为LED的字模 0 1 2 3 4 5 6 7 8 9 a b c d e f
unsigned char LED7Code[] = {~0x3F,~0x06,~0x5B,~0x4F,~0x66,~0x6D,~0x7D,~0x07,~0x7F,~0x6F,~0x77,~0x7C,~0x39,~0x5E,~0x79,~0x71};
int x;
int main(void){
RCC_Configuration(); //时钟设置
USART1_Init(115200); //串口初始化波特率
GPIO_Configuration55();//GPIO_Configuration44();
GPIO_Write(GPIOA, LED7Code[8]);//数码管全亮
while(1)
{
x=keyscan55();//扫描按键,返回按键值
//x=keyscan44();)
printf("%d ",x);//串口输出
if (x>=0)
{
GPIO_Write(GPIOA, LED7Code[x]); //显示按键值;
}
}
}
二、LCD输出
步骤:
1.初始化LCD显示屏
2.清屏
3.写数据
LCD点阵大小 12864 即8行16列
每一个英文字符占816个字节,即2行1列,两行可以显示16个英文字符
每一个中文字符占16*16个字节,即2行2列,两行可以显示8个中文字符
如果超出不显示,以上为默认情况,其他函数详见LCD12864.c文档
可使用PCTOLCD生成需要的点阵
//LCD主函数
#include "stm32f10x.h" // Device header
#include "stm32f103_config.h"
#include "lcd12864.h"
#include "Font.h"
#include "Image.h"
int main(void)
{
delay_ms(100);//延时100毫秒
LCD_Init();/初始化显示屏
LCD_Clr(); //清屏
LCD_WriteEnglish(2,0,1+'0');
LCD_WriteEnglish(2,8,2+'0');
LCD_WriteEnglish(2,2*8,3+'0');
LCD_WriteEnglish(2,3*8,4+'0');
LCD_WriteEnglish(2,4*8,5+'0');
LCD_WriteEnglishString(2,5*8,(unsigned char *)" end");
LCD_WriteEnglishString(4,0,(unsigned char *)"0123456789ABCDEF");*/
LCD_WriteEnglishString(0,0,(unsigned char *)" HUNAN CITY");
LCD_WriteEnglishString(2,0,(unsigned char *)" University");
LCD_WriteChineseString(4,0,(unsigned char *)hanzi,6);
//LCD_DispImg(2,48,60,60,(unsigned char *)Fig0);
}
线路连接:
三、TFTLCD输出
NEWLab的TFT模块采用了ILI9341控制器,其外形如图85所示。该模块有如下特点:
2.8寸屏幕。 320×240的分辨率。 16位真彩显示。 自带触摸屏,可以用来作为控制输入
步骤:
与LCD相似
1.初始化TFTLCD
2.相关函数的使用如下代码
线路连接:
显示图片步骤:
1.打开Image2Lcd软件
2.点击右上角打开按钮,选择你要的图片
3.其他设置如下图
首先,按照图811所示,配置Image2LCD的工作模式。其中,
输出数据类型:“C语言数组(.C)”
扫描模式:水平扫描
输出灰度:16位真彩色
最大宽度和高度:与图片的大小和液晶屏的大小相匹配。
选择包含图像头数据
选择自底至顶扫描
注:像素大小不得超过240320 若超过,请使用如"图画"软件缩减图片尺寸
4.创建一个img.h文件,将生成的c语言数组放入文件中,使用GLCD_DrawBitmap (0 ,0, 180, 240, (const uint8_t *)gImage_test)函数实现图像显示
#include "stm32f10x.h" // Device header
#include "GLCD_Config.h"
#include "Board_GLCD.h"
#include "img.h"
#include "delay.h"
#include "stdlib.h"
extern GLCD_FONT GLCD_Font_16x24;//外部字体变量
extern GLCD_FONT GLCD_Font_6x8;
uint32_t n;
double num;
char str[25];
int main(void)
{
GLCD_Initialize();//初始化LCD
GLCD_ClearScreen();//清屏
GLCD_SetForegroundColor(GLCD_COLOR_BLACK);//前景颜色
GLCD_SetBackgroundColor(GLCD_COLOR_WHITE);//背景颜色
GLCD_SetFont(&GLCD_Font_16x24);//设置字体,高度25,宽度16
//hight 24*13=312 < 320 lenth 16*15=240
GLCD_ClearScreen(); //清屏
//GLCD_SetForegroundColor(GLCD_COLOR_BLACK);
//GLCD_DrawPixel(11,22);//1.绘制一个像素点
//GLCD_DrawHLine(1,1,120);//2.绘制横线
//GLCD_DrawVLine(1,1,120);//3.绘制竖线
//GLCD_DrawHLine(1,120,120);
//GLCD_DrawVLine(120,1,120);
//4.绘制字符串
num = 123.4567;
sprintf(str, " %f" , num);
GLCD_SetFont(&GLCD_Font_6x8);
//GLCD_SetFont(&GLCD_Font_16x24);
//hight 24*13=312 < 320 lenth 16*15=240
GLCD_DrawString(24,24,str);
//GLCD_DrawString(24, 24,"HuNan City");//
//5.绘制矩形框
//GLCD_SetForegroundColor(GLCD_COLOR_GREEN);//Ç°¾°£¨×Ö·û£©ÑÕɫΪÂÌÉ«
//GLCD_DrawRectangle(10,10,120,120);
//6.绘制线条,
//GLCD_SetForegroundColor(GLCD_COLOR_BLACK);//
//GLCD_DrawBargraph(30,0,200,40,10);//x,y,weight(0~240),height(0~320),val<100
//7.绘制图像
//GLCD_DrawBitmap (0 ,0, 180, 240, (const uint8_t *)gImage_test);//ÏÔʾͼÏñ
//x,y,width(<=240),height(<=320)
//8.向下滚动屏幕n个像素点,滚动条
//GLCD_VScroll(12);
//delay_s(1);
//GLCD_VScroll(100);
while(1)
{
//GLCD_VScroll(40);
//delay_s(1);
}
}
三、串口输出
串口通信接口为USART
TX代表发送 RX代表接收
RX1 PA10 TX1 PA9 连接底部引脚 所以可以直接通过NEWLAB板通信
RX2 PA2 TX2 PA3
RX3 PB11 TX3 PB10
串口发送代码实现:
导入usart.c驱动文件,驱动文件已经设置好三个串口的引脚,只要在使用时更改定义的引脚即可,其他不需要改变
stm32中,c语言的printf函数被默认打印在串口上
串口接收代码实现
查询方式接收:将接收到的数据发送回电脑,usart.c文件中,在串口1初始化函数中,将USART_ITConfig是否开启串口中断函数的ENABLE改为DISABLE,防止调用中断函数
使用中断方式接收:可以在数据收到的第一时间,马上跳转到中断函数来做及时的处理,提高实时性
#include "stm32f10x.h" //STM32头文件
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "usart.h"
#include "key.h"
extern unsigned char LED7Code[];
int main (void){//
u8 a;
//初始化程序
RCC_Configuration(); //时钟设置
LED8_Init();//8位数码管初始化
USART1_Init(115200); //串口初始化
while(1){
//实现串口控制8位数码管
if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE) != RESET){ //查询串口标志位
a = USART_ReceiveData(USART1);//读取接收到的数据
printf("%c",a); //把收到的数据发送到电脑
if(a>='0'&&a<='9'){
GPIO_Write(GPIOA,LED7Code[a-'0']);//显示数字
}
}
LATCH_KEY1();//按下key1,发送key1被按下信息
LATCH_KEY2();//按下key2,发送key2被按下信息
// delay_ms(1000);
}
}
用例
WIFI模块
步骤:
1.连接
2.平台命令获取及分析
3.单片机数据发送
接线:
stm32 P10 Tx - wifi RX
stm32 P11 Rx - wifi TX
int main()
{
uint8_t IpData[128];
int8_t temp;//检验热点是否连接成功,成功为1,失败为0
uint8_t TryCount=0;
RCC_Configuration(); //系统时钟初始化
TIM2_Init();
USART1_Init(115200);//串口一初始化
printf("init...\r\n");
UART4_Init(115200);//WiFi串口四初始化
for(TryCount=0; TryCount<3; TryCount++)//三次连接
{
printf("start link %d times.\r\n",TryCount+1);
temp=ConnectToServer((char *)MY_DEVICE_ID, (char *)MA_SECRET_KEY);//连接热点和服务器
if(temp != 0)//连接失败 temp = -1:WIFI模式设置错误 -2:WIFI连接错误 -3:端口或地址错误 -4:第一次握手数据发送错误 -5未响应错误
{
printf("Connect To Server ERROR=%d\r\n",temp);
}
else
{
break;
}
}
printf("link success\r\n");
ClrAtRxBuf();//清空AT缓存
//==================以上为WIFI连接函数===========================
while(1)
{
//===================以下为WIFI接收到云平台数据函数==================
if(F_AT_RX_FINISH)//判断是否接收到UART4_RX数据
{ // 接收到数据包
ESP8266_GetIpData((uint8_t *)AT_RX_BUF, (char *)IpData);//获取数据,存入IpData
USER_DataAnalysisProcess((char *)IpData);//分析数据,在这个函数里对数据进行处理
memset(IpData, 0x00, 128);//清空数据
ClrAtRxBuf();
}
///==================已下为WIFI发送单片机数据到云平台函数==================
if(TimeCount >= 1000)//10S发送一次数据 timeCount每计数100次代表1s
{
TimeCount=0;
ESP8266_SendSensor((char *)"wind", (char *)"2020-10-16 14:10:26", GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_0));//发送数据函数,参数1标识名 参数二:时间 参数三:数据如温度,低频高低
ClrAtRxBuf();
}
}
}
//=================以下为分析函数具体实现============
void USER_DataAnalysisProcess(char *RxBuf)
{
char *cmdid = NULL;
uint8_t TxetBuf[128];//发送数据
if(strstr((const char *)RxBuf, (const char *)PING_REQ) != NULL)//心跳请求//strstr()查找子串在主串第一次出现的位置,判断是否收到数据
{
if(ESP8266_IpSend((char *)PING_RSP, strlen((const char *)PING_RSP)) < 0)//响应心跳
{//发送失败
printf("发送心跳包失败!\r\n");
}
else
{
printf("心跳包!\r\n");
}
}
else if(strstr((const char *)RxBuf, (const char *)"\"t\":5") != NULL)//命令请求//收到请求
{
if(strstr((const char *)RxBuf, (const char *)"\"apitag\":\"ctrl\"") != NULL)//判断收到的标识名
{
memset(TxetBuf,0x00,128);//清空缓存
///=====================操作代码书写区域=====================
//==============判断收到的数据,在里面执行需要的操作==============
if((strstr((const char *)RxBuf, (const char *)"\"data\":1") != NULL))
{
GPIO_SetBits(GPIOA,GPIO_Pin_0);
cmdid = USER_GetJsonValue((char *)RxBuf, (char *)"cmdid");
sprintf((char *)TxetBuf,"{\"t\":6,\"cmdid\":%s,\"status\":0,\"data\":1}",cmdid);
//printf("%s\r\n",TxetBuf);
if(ESP8266_IpSend((char *)TxetBuf, strlen((char *)TxetBuf)) < 0)
{//发送失败
//printf("发送响应失败!\r\n");
}
}
else if((strstr((const char *)RxBuf, (const char *)"\"data\":0") != NULL))//关灯
{
GPIO_ResetBits(GPIOA,GPIO_Pin_0);
cmdid = USER_GetJsonValue((char *)RxBuf, (char *)"cmdid");
sprintf((char *)TxetBuf,"{\"t\":6,\"cmdid\":%s,\"status\":0,\"data\":0}",cmdid);
//printf("%s\r\n",TxetBuf);
if(ESP8266_IpSend((char *)TxetBuf, strlen((char *)TxetBuf)) < 0)
{//发送失败
printf("发送响应失败!\r\n");
}
}
}
}
}
#ifndef _CloudReference_h_
#define _CloudReference_h_
//================在CloudReference.h设置WIFI名称和密码以及设备标识和传输密钥
#define WIFI_AP "xin"//WiFi热点名称
#define WIFI_PWD "987654321" //WiFi密码
#define WIFI_AP1 "zhjt_220"//WiFi热点名称
#define WIFI_PWD1 "12345678zhjt" //WiFi密码
#define SERVER_IP "120.77.58.34" //服务器IP地址
#define SERVER_PORT 8600 //服务器端口号
#define MY_DEVICE_ID "light2018052790"//设备标识
#define MA_SECRET_KEY "1d1c815e2a504ff9abcf6301134f27d3"//传输密钥
#endif /*_CloudReference_h_*/
语音模块
使用xfs5152ce.c和usart3.c极fifo.c文件,主要功能语音识别和文本合成
步骤:
/***************************************************************
* Name : MAIN.C
* Data : 2019.7.15
* Author : NIEAOWEI
* Note : 本实验主要是测试语音模块,连续读不卡顿,中断读,
以及语音识别功能。
****************************************************************/
#include "usart3.h"
#include "delay.h"
#include "fifo.h"
#include "xfs5152ce.h"
#include "usart1.h"
int main(){
uint8_t data[10];
uint8_t a;
delay_init();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
Usart1_Init(115200);
usart3_init();
delay_ms(1);
printf("start...\r\n");
xfs_voice_start((unsigned char *)"请说出启动指令",XFS_FORMAT_GBK,1);//语音合成播放指定文本 *data 需要合成播放的文本 format 编码格式 wait_finish 是否等待上次合成结束
xfs_voice_start((unsigned char *)"请说出启动指令",XFS_FORMAT_GBK,1);//语音合成函数,可以播放想要的信息,参数1 要播放的文字 参数2 编码格式 参数3 是否等待上次合成结束,1等待
xfs_voice_start((unsigned char *)"请说出启动指令",XFS_FORMAT_GBK,1);
printf("%d,%d\r\n",usart3_rx_fifo.in,usart3_rx_fifo.out);
//*delay_ms(1000);
if(xfs_recognize(&a, 5000) == 1)
{
xfs_voice_start((unsigned char *)"语音识别成功", XFS_FORMAT_GBK, 1);
sprintf((char *)data,"%d",a);
xfs_voice_start((unsigned char *)data,XFS_FORMAT_GBK,1);
xfs_voice_start((unsigned char *)cmd_word_list[a],XFS_FORMAT_GBK,1);
}else{
xfs_voice_start((unsigned char *)"语音识别失败",XFS_FORMAT_GBK,1);
}
printf("re :%d\r\n",a);
for(a=0;a<100;a++){
printf("%x,",usart3_rx_fifo.data[a]);
}
printf("%d,%d\r\n",usart3_rx_fifo.in,usart3_rx_fifo.out);
while(1){
delay_ms(1000);
printf("runnig...\r\n");
};
}
四、ADC输出
步骤:
1.时钟初始化
2.ADC初始化
3.声明外部变量,获取电压值,通过公式转化成对应的数据值
连线:
温度光照传感器J6,接PB0
ADC_IN1 PA1
ADC_IN4 PA4
ADC_IN5 PA5
ADC_IN6 PA6
ADC_IN7 PA7
ADC_IN8 PB0
ADC_IN9 PB1
ADC_IN10 PC0
ADC_IN11 PC1
ADC_IN12 PC2
ADC_IN13 PC3
#define ADC1_DR_Address ((uint32_t)0x4001244C)//ADC1外设地址
#define ADCPORT GPIOB //定义ADC接口
#define ADC_CH8 GPIO_Pin_0
#define ADC_CH9 GPIO_Pin_1
vu16 ADC_DMA_IN5; //ADC数值存放的变量
void ADC_DMA_Init(void){ //DMA初始化设置
DMA_InitTypeDef DMA_InitStructure;//定义DMA初始化结构体
DMA_DeInit(DMA1_Channel1);//复位DMA通道1
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; //定义 DMA通道外设基地址=ADC1_DR_Address
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADC_DMA_IN5; //定义DMA通道ADC数据存储器(其他函数可直接读此变量即是ADC值) //修改一:获取ADC数值地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//指定外设为源地址
DMA_InitStructure.DMA_BufferSize = 1;//定义DMA缓冲区大小(根据ADC采集通道数量修改) //修改二:获取ADC的通道数
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//当前外设寄存器地址不变
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;//当前存储器地址:Disable不变,Enable递增(用于多通道采集) //修改三:多道采集用Enable
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//定义外设数据宽度16位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //定义存储器数据宽度16位
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//DMA通道操作模式位环形缓冲模式
DMA_InitStructure.DMA_Priority = DMA_Priority_High;//DMA通道优先级高
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//禁止DMA通道存储器到存储器传输
DMA_Init(DMA1_Channel1, &DMA_InitStructure);//初始化DMA通道1
DMA_Cmd(DMA1_Channel1, ENABLE); //使能DMA通道1
}
void ADC_GPIO_Init(void){ //GPIO初始化设置
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);//使能DMA时钟(用于ADC的数据传送)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);//使能ADC1时钟
GPIO_InitStructure.GPIO_Pin = ADC_CH8; //选择端口 //修改四: 设置获取ADC端口的引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //选择IO接口工作方式
GPIO_Init(ADCPORT, &GPIO_InitStructure); //修改五:ADCPORT修改接口
}
void ADC_Configuration(void){ //初始化设置
ADC_InitTypeDef ADC_InitStructure;//定义ADC初始化结构体变量
ADC_GPIO_Init();//GPIO初始化设置
ADC_DMA_Init();//DMA初始化设置
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//ADC1和ADC2工作在独立模式
ADC_InitStructure.ADC_ScanConvMode = ENABLE; //使能扫描
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//ADC转换工作在连续模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//有软件控制转换
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//转换数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = 1;//顺序进行规则转换的ADC通道的数目(根据ADC采集通道数量修改) //修改六:通道数
ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器
//设置指定ADC的规则组通道,设置它们的转化顺序和采样时间
//ADC1,ADC通道x,规则采样顺序值为y,采样时间为28周期
ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_28Cycles5);//ADC1选择信道x,采样顺序y,采样时间n个周期 //修改七:信道要改为对应引脚通道
ADC_DMACmd(ADC1, ENABLE);// 开启ADC的DMA支持(要实现DMA功能,还需独立配置DMA通道等参数)
ADC_Cmd(ADC1, ENABLE);//使能ADC1
ADC_ResetCalibration(ADC1); //重置ADC1校准寄存器
while(ADC_GetResetCalibrationStatus(ADC1));//等待ADC1校准重置完成
ADC_StartCalibration(ADC1);//开始ADC1校准
while(ADC_GetCalibrationStatus(ADC1));//等待ADC1校准完成
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能ADC1软件开始转换
}
#include "stm32f10x.h" //STM32头文件
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "adc.h"
extern vu16 ADC_DMA_IN5; //声明外部变量
int main (void){//主程序
delay_ms(500); //上电时等待其他器件就绪
RCC_Configuration(); //系统时钟初始化
ADC_Configuration(); //ADC初始化设置
USART1_Init(115200);
while(1){
printf("值:%0.3f\r\n",ADC_DMA_IN5*(3.3/4095));//光照公式
delay_ms(500); //延时
}
}
用途
温度光照传感器
使用的是 temp_light.c temp_light.h源文件
实验步骤:
1.初始化温度光照
2.使用GetTemp函数获取温度
3.使用GetLight函数获取光照
接线:
温度输出口:PC0
光照输出口:PC1
uint8_t GetTemp(){
uint16_t temp;
temp=GetADC_Time(TEMP_CH,10);
printf("temp adc value:%d\r\n",temp);
return calculateTemperature(calculateResValue(temp));
}
/***************************************************************
* @brief 获取一次光照值,以百分比的形式计算
* @param
* @retval float 光照值
****************************************************************/
//
float GetLight(){
uint16_t light;
light=GetADC_Time(LIGHT_CH,10);
printf("light adc value:%d\r\n",light);
return 100-((float)light*1000/4096)*100/1000;
}
#include "usart1.h"
#include "delay.h"
#include <stdio.h>
#include "temp_light.h"
int main(){
Byte temp[20];
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
Usart1_Init(115200);
delay_init();
TEMP_LIGHT_Init();
printf("runnning...\r\n");
while(1){
printf("temp:%d\r\n",GetTemp());
printf("light:%d\r\n",GetLight());
delay_ms(1000);
}
}
五、DAC输出
步骤:
1.设置系统时钟
2.初始化DAC
3.DAC_OutVoltage(float Voltage)设置引脚输出电压值
接线:
DAC输出口
DAC_OUT1–PA4
DAC_OUT2–PA5
void DAC_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
DAC_InitTypeDef DAC_InitType;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE ); //使能PORTA通道时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE ); //使能DAC通道时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; // 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入(STM32没有模拟输出模式,这里只好配置为模拟输入)
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
DAC_InitType.DAC_Trigger=DAC_Trigger_None; //不使用触发功能 TEN1=0
DAC_InitType.DAC_WaveGeneration=DAC_WaveGeneration_None;//不使用波形发生
DAC_InitType.DAC_LFSRUnmask_TriangleAmplitude=DAC_LFSRUnmask_Bit0;//屏蔽、幅值设置
DAC_InitType.DAC_OutputBuffer=DAC_OutputBuffer_Disable ; //DAC1输出缓存关闭 BOFF1=1
DAC_Init(DAC_Channel_1,&DAC_InitType); //初始化DAC通道1
DAC_Cmd(DAC_Channel_1, ENABLE); //使能DAC1
DAC_SetChannel1Data(DAC_Align_12b_R, 0); //12位右对齐数据格式设置DAC值,默认输出0V
}
void DAC2_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
DAC_InitTypeDef DAC_InitType;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE ); //使能PORTA通道时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE ); //使能DAC通道时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; // 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入(STM32没有模拟输出模式,这里只好配置为模拟输入)
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
DAC_InitType.DAC_Trigger=DAC_Trigger_None; //不使用触发功能 TEN1=0
DAC_InitType.DAC_WaveGeneration=DAC_WaveGeneration_None;//不使用波形发生
DAC_InitType.DAC_LFSRUnmask_TriangleAmplitude=DAC_LFSRUnmask_Bit0;//屏蔽、幅值设置
DAC_InitType.DAC_OutputBuffer=DAC_OutputBuffer_Disable ; //DAC1输出缓存关闭 BOFF1=1
DAC_Init(DAC_Channel_2,&DAC_InitType); //初始化DAC通道2
DAC_Cmd(DAC_Channel_2, ENABLE); //使能DAC2
DAC_SetChannel2Data(DAC_Align_12b_R, 0); //12位右对齐数据格式设置DAC值,默认输出0V
}
//设置通道1输出电压
// Voltage----电压值,取值范围为0~3.3V
void DAC1_OutVoltage(float Voltage)
{
uint16_t data;
data=(uint16_t)(Voltage*4095/3.3);//换算为12位整数值
DAC_SetChannel1Data(DAC_Align_12b_R,data);//12位右对齐数据格式设置DAC值
DAC_SoftwareTriggerCmd(DAC_Channel_1,ENABLE); //启动转换
}
void DAC2_OutVoltage(float Voltage)
{
uint16_t data;
data=(uint16_t)(Voltage*4095/3.3);//换算为12位整数值
DAC_SetChannel2Data(DAC_Align_12b_R,data);//12位右对齐数据格式设置DAC值
DAC_SoftwareTriggerCmd(DAC_Channel_2,ENABLE); //启动转换
}
#include "stm32f10x.h" //STM32
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "dac.h"
int main (void){
float voltage=2;
delay_ms(500); //
RCC_Configuration(); // 系统时钟初始化
DAC_Configuration(); //DAC初始化设置
USART1_Init(115200);
DAC1_OutVoltage(voltage);
while(1){
while(1)
{
delay_ms(1000);
if (voltage<3.3)
{voltage+=0.1;}
else
{voltage=0;}
//voltage=3.3;
DAC1_OutVoltage(voltage);
while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET);
printf("DAC输入的数字为:%d",(uint16_t)(voltage*4095/3.3));
printf("DAC输出电压为:%.3f\n",voltage);
}
}
}
比赛总结:
熟悉stm32各个引脚的初始化,会各个模块的各种逻辑使用