博主在网上找到了一些代码支持,但是或多或少的存在一些问题,博主在这里直接上代码了,需要的自己研究就可以了,亲测可用
参考文章:(3条消息) MAX6675使用笔记_自小吃多的博客-CSDN博客
max6675使用说明:(3条消息) MAX6675使用笔记_Delta-delta的博客-CSDN博客
代码说明:
使用的板子是STM32F103C8T6最小开发板
代码功能:将6675的数据读取并通过串口传输到串口调试助手上
spi的部分不知道为什么使用硬件读不出来数据,这里我用的软件模拟,也就是说你可以吧管脚设置到任何一个你需要的管脚上
使用说明:
1、MAX6675博主是自己焊接的,因为器件很精密,要求焊接温度建议在300℃下不超过15秒。焊接过热可能会导致芯片损坏。
2、热电偶线路长短会影响数据精度,芯片到MCU的线距会影响时钟频率
3、一定要对准6675的时钟来,频率不能超过2M,只能慢不能快
4、在电路设计上,连接接热电偶负极的管脚建议接地,可以提高稳定性
在热电偶正负极之间链接一个100nF的电阻可以减少干扰
(博主后期遇到了大功率用电器启动、运行过程中温度读数清零的现象,通过增加电阻已解决)
main.c
#include "stm32f10x_conf.h" #include "LED.h" #include "delay.h" #include "usart.h" #include "MAX6675.h" #include "stdio.h" void USART1_IRQHandler(void)//这是USART接收到数据后触发的中断处理函数(如果你使用了中断接收的方式) { uint8_t data; if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET) { data = usart1_recv_byte(); usart1_send_byte(data); } } int main (void) { float t; LED_init(); delay_init(); usart1_init(); MAX6675_Init(); printf("开始检测\n"); while(1) { t = read_temper(); printf("%.5f\n", t); // t = MAX6675_ReadReg(); // print_binary(t); printf("\n"); LED_on(); delay_ms(1000); LED_off(); delay_ms(1000); } }
讯享网
MAX6675.h
讯享网#ifndef __MAX6675_H #define __MAX6675_H #include "stm32f10x_conf.h" /*============================================================*/ /*SPI1管脚设置为: */ /* PA4 -> cs片选 PA5 -> SCK时钟 */ /* PA6 -> MISO主出从入 PA7 -> MOSI 主出从入 */ /*============================================================*/ void MAX6675_Init(void); //初始化 unsigned int MAX6675_ReadReg(void); //读取全部16位数据 float read_temper(void); //读取温度 void print_binary(unsigned int number); //这是打印二进制数的打印函数 #endif
MAX6675.c
#include "MAX6675.h" #include "delay.h" #include "usart.h" #include "stdio.h" /*==========================================================*/ /*SPI1管脚设置为: */ /* PA4 -> cs片选 PA5 -> SCK时钟 */ /* PA6 -> MISO主出从入 PA7 -> MOSI 主出从入 */ /*==========================================================*/ void MAX6675_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; //GPIO初始化结构体 RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE ); //使能APB2总线上的GPIOA组时钟 GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5; //配置PIN4, 5管脚 GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; //设置模式为推挽输出 GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; //输出速率为50MHz GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_SetBits(GPIOA, GPIO_Pin_4); //拉高片选线电平 GPIO_ResetBits(GPIOA, GPIO_Pin_5); //拉低时钟线 GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6; //MISO管脚 GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入 GPIO_Init(GPIOA, &GPIO_InitStruct); } unsigned int MAX6675_ReadReg(void) { unsigned char i; unsigned int dat; i = 0; dat = 0; GPIO_ResetBits(GPIOA, GPIO_Pin_4); //拉低片选开始传输 GPIO_ResetBits(GPIOA, GPIO_Pin_5); //拉低时钟准备传输 delay_us(2); for(i=0; i<16; i++) { GPIO_SetBits(GPIOA, GPIO_Pin_5); //拉高时钟线 delay_us(1); dat = dat<<1; if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6)==1) dat = dat|0x01; GPIO_ResetBits(GPIOA, GPIO_Pin_5);//拉低时钟结束传输 delay_us(1); } GPIO_SetBits(GPIOA, GPIO_Pin_4); //拉高片选,传输结束 delay_us(2); return dat; } float read_temper() //读取温度 { int d; d=MAX6675_ReadReg(); //读取当前温度 d = d<<1; //去掉伪符号位 if(d&0x08) //MAX6675是否在线 printf("未检测到热电偶"); else printf("设备在线"); return ((d>>4)&0x0fff)*0.25; } void print_binary(unsigned int number) { if (number >> 1) { print_binary(number >> 1); } putc((number & 1) ? '1' : '0', stdout); }
delay.h
讯享网#ifndef __DELAY_H #define __DELAY_H #include "stm32f10x_conf.h" #define SYSCLK 72 extern void delay_init(void); //初始化函数 extern void delay_ms(uint16_t nms); //毫秒级别的延迟 extern void delay_us(uint32_t nus); //纳秒级别的延迟 #endif
delay.c
#include "delay.h" static uint8_t fac_us=0; //us延时倍乘数 static uint16_t fac_ms=0; //ms延时倍乘数 void delay_init(void) { SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //为系统定时器选择时钟为 HCLK 8分频 72MHz/8 = 9MHz fac_us = SYSCLK / 8; //微秒的倍乘数 = 72 / 8 = 9 //X * fac_us就相当于有X个微秒 fac_ms = (u16)fac_us * 1000; //每个ms需要的systick时钟数(1ms = 1000us),所以fac_us*1000 //X * fac_ms就相当于有X个毫秒 } void delay_us(uint32_t nus)//微秒级别的延迟 { uint32_t midtime; //定义了一个uint32_t的变量 //保存寄存器的状态 SysTick->LOAD/*重装载值寄存器*/ = nus * fac_us; //时间加载(相当于有nus个微妙) SysTick->VAL = 0x00; //清空当前值寄存器,以为系统会自动去重装载值寄存器去加载 SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; //给状态及控制寄存器的第0位(是否开启)至1,相当于打开了计时器 do { midtime = SysTick->CTRL; //把状态及控制寄存器的数据赋值给变量 } while((midtime & 0x01) && !(midtime & (1 << 16))); //当第0位(是否开启)是1,并且第16位(判断计数器是否记到0)到0的时候跳出循环 SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; //给状态及控制寄存器的第0位(是否开启)至0,相当于关闭了计时器 SysTick->VAL = 0X00; //清空当前值寄存器 } void delay_xms(uint16_t nms) { uint32_t midtime; SysTick->LOAD = (uint32_t)nms*fac_ms; //时间加载(SysTick->LOAD为24bit) SysTick->VAL = 0x00; //清空计数器 SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; //开始倒数 do { midtime = SysTick->CTRL; } while((midtime & 0x01) && !(midtime & (1 << 16)));//等待时间到达 SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; //关闭计数器 SysTick->VAL = 0X00; //清空计数器 } void delay_ms(u16 nms) { u8 repeat = nms / 540; //记录有多少个整的540ms u16 remain = nms % 540; //记录有多少个不够540ms //理论上只要小于1864都可以,不一定非得是540 while(repeat) { delay_xms(540); repeat--; } if(remain)delay_xms(remain); }
usart.h
讯享网#ifndef __USART_H #define __USART_H #include "stm32f10x_conf.h" /*================================================*/ /*由开发手册总线图可知,C8T6的USART1在APB1总线上 */ /* USART1_TX段在PA9管脚 */ /* 发送管脚需要配置为推挽的复用功能 */ /* USART1_RX段在PA10管脚 */ /* 接收管脚需要配置为浮空的输入功能 */ /*================================================*/ typedef void(*usart1_handler)(uint8_t); //定义了函数指针类型 extern void usart1_init(void); //初始化USART1的函数 extern void usart1_send_byte(uint8_t); //通过USART1发送一个字节 extern void usart1_send_data(uint8_t* buff); //通过USART1发送数据 extern uint8_t usart1_recv_byte(void); //通过USART1接收一个字节 extern void set_usart1_handler(usart1_handler h); //接收中断函数 #endif
usart.c
#include "usart.h" #include "stdio.h" /*============================宏定义部分=================================*/ #pragma import(__use_no_semihosting)//这是标准库需要的支持函数 /*============================变量定义===================================*/ struct __FILE //弱定义(两个下划线)一下FILE类型 { int a; }; FILE __stdout; //弱定义一下标准输出 void _sys_exit(int x) //重定义函数,这步操作相当于禁用半主机模式 { } int fputc(int c, FILE *f)//把fputc重定向到USART1的发送 { usart1_send_byte(c); return c; } /*============================函数实现===================================*/ void usart1_init(void) //USART1的初始化函数 { GPIO_InitTypeDef GPIO_Value; //定义了初始化GPIO的结构体类型的变量 USART_InitTypeDef USART_Value; //定义了初始化USART的结构体类型的变量 NVIC_InitTypeDef NVIC_Value; //定义了初始化NVIC的结构体类型的变量 //使能APB2总线上的GPIOA组的时钟,和UASART1的时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE); /*从芯片开发手册的总线图上可以查看你的串口在那条总线上, 后面的管脚服用列表也可以看你的输入输出的管脚,使能对应组的时钟即可*/ GPIO_Value.GPIO_Mode = GPIO_Mode_AF_PP; //选择了推挽的复用模式 GPIO_Value.GPIO_Pin = GPIO_Pin_9; //选择了9号管脚 GPIO_Value.GPIO_Speed = GPIO_Speed_50MHz; //选择了50MHz的输出速率 GPIO_Init(GPIOA, &GPIO_Value); //按照上述配置初始化GPIOA组的管脚 GPIO_Value.GPIO_Mode = GPIO_Mode_IN_FLOATING; //选择了浮空的输入模式 GPIO_Value.GPIO_Pin = GPIO_Pin_10; //选择了10号管脚 GPIO_Init(GPIOA, &GPIO_Value); //按照上述配置初始化GPIOA组的管脚 USART_Value.USART_BaudRate = ; //选择了的波特率 USART_Value.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//选择了关闭硬件流控 USART_Value.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//选择了发送和接收模式 USART_Value.USART_Parity = USART_Parity_No; //选择了没有奇偶校验 USART_Value.USART_StopBits = USART_StopBits_1;//选择了1个停止位 USART_Value.USART_WordLength = USART_WordLength_8b;//选择了8个数据位 USART_Init(USART1, &USART_Value); //按照上述配置初始化USART1 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//配置组优先级和子优先级的所占比例 NVIC_Value.NVIC_IRQChannel = USART1_IRQn; //选择了USART1的中断号 NVIC_Value.NVIC_IRQChannelCmd = ENABLE; //使能该中断 NVIC_Value.NVIC_IRQChannelPreemptionPriority = 2;//配置组优先级的级别为2 NVIC_Value.NVIC_IRQChannelSubPriority = 2; //配置子优先级的级别为2 NVIC_Init(&NVIC_Value); //按照上述配置初始化NVIC USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //把USART1的接收配置为中断的模式 USART_Cmd(USART1, ENABLE); //选择了使能USART1的功能 } void usart1_send_byte(uint8_t data) //通过USART1发送数据 { USART1->SR; //读取SR寄存器 USART_SendData(USART1, data); //把形参data存储的数据通过USART1进行发送 while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET); //以死等的方式等待USART1的数据发送成功 USART_ClearFlag(USART1, USART_FLAG_TC); //清除USART1的发送成功的标志状态 } void usart1_send_data(uint8_t*buf) //通过USART1发送多个字节数据 { while(*buf) { usart1_send_byte(*buf); buf++; } } uint8_t usart1_recv_byte(void) //通过USART1接收数据 { uint8_t data = 0; //用于保存接收到的数据 if(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == SET)//判断USART1是否接收到了数据 { data = USART_ReceiveData(USART1); //读取USART1接收到的数据 USART_ClearFlag(USART1, USART_FLAG_RXNE); //清除USART1接收数据的标志状态 } return data;//把读取到的数据返回 }
欢迎在文章下讨论分享问题,博主虽然也是小白,但也会尽力的帮助解决问题的~~

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/14821.html