tag 标签: stm8s105

相关博文
  • 热度 22
    2016-1-5 17:16
    5006 次阅读|
    6 个评论
    写在之后:排版有些混乱,见谅哈。转载请注明出处。 写在之后的之后: 我再放几张实物图哈哈,由于我之前在STM32F0移植的时候没有放照片,只能用现在用STM8S105的照片先拿上来,以飨读者。手头还有一些东西玩玩,就是手机控制LCD,这是目前的一部分。由于目前还没做出来,只是处于功能完善阶段,所以有些简陋。小弟就做个抛砖引玉。 首先感谢ST王先生给我一块STM32F0-Discovery,实话说,在此之前也没想到会拿到。EDN CHINA 诚不欺我哈哈,废话少说,今天给大家带来的是一款温湿度传感器DHT21(AM2301), 这是一款性能优良的温湿度监测传感器,最近公司要求在STM32F0上还有在STM8S105上面进行移植,为下一步项目做一些准备。Discovery 确实是一个很好的开发环境,集成了STLINK,很方便调试和下载,做工也堪称精炼。 在这里也感慨一下,由于本人走嵌入式这条路自己在网络上收益良多,在这里也感谢各位陌生而亲切的同行,也希望以此为契机,大家集思广益,共同建设EDN CHINA的大家庭。 有问题大家联系我,鄙人乐向哲,362245396@qq.com. 简单说一下,温湿度传感器DHT21(AM2301)是一款优良的温湿度传感器,具体的介绍在我的附件里面。 我附上的附件有以下三个 1,温湿度传感器DHT21(AM2301)的介绍,时序图,还有汇编,C51例程 2,温湿度传感器DHT21(AM2301) 在stm32F0上的移植 3,温湿度传感器DHT21(AM2301) 在stm8S105上面的移植 由于时间有限,我把重点的部分说一下 首先,温湿度传感器DHT21(AM2301)是单总线。 时序图入上所示,不知道为什么我的这边上传不了图片 简单说一下, 1,接线是简单的。如图1_1所示 图1_1 /****** 黑色: GND 红色: VCC 黄色: 接MCU的普通IO (注意不要接到特殊IO 如VSS VDD 等等) 第四线:NC *******/ 2,时序是: 空闲时总线为高电平,通讯开始时主机(MCU)拉低总线500us后释放总线,延时20-40us后主机开始检测从机(DHT21)的响应信号。从机的响应信号是一个80us左右的低电平,随后从机在拉高总线80us左右代表即 将进入数据传送。(要注意程序给主机一个下降沿) 如图2_1所示: 图2_1 如图2_2所示: 图2_2 3,引脚配置如下:这是重点! 这是重点! 这是重点! 重要的事情说四遍。。。 STM32F0版本 上拉输入是必须的!上拉输入是必须的!上拉输入是必须的! ***是中国的!***是中国的!***是中国的!***是中国的!说远了。。 stm32F0版本 void GPIO_Initializations(void) { GPIO_InitTypeDef GPIO_InitStructure; /* USART1_Tx/Rx Configuration *///USART1接口初始化 GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);//数据手册中有介绍 GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //PA9/10 alternate function GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3; //high speed GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//pushpull mode GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//可以没有上拉 GPIO_Init(GPIOA, &GPIO_InitStructure); /* GPIOB Configuration */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;//AM2301接口初始化 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//output mode GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3;//high speed GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //上拉输入 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//pull up GPIO_Init(GPIOB, &GPIO_InitStructure); } STM8S105版本: #define SET_OUT_STATUS { PC_DDR |= (1 #define SET_IN_STATUS { PC_DDR &=~(1 } } C51 汇编见附件 《AM2301(DHT21)规格书》 4,“1” 和 “0”的区别:两者的区别在于 高电平时间的长短 “0” 如图 4_1所示 图4_1 “1” 如图 4_2所示 图4_2 5,关键程序演示和讲解 stm32F0版本 unsigned char AM23XX_Read(void)//读取温湿度 { unsigned char i, AM23XX_answerFlag=0; unsigned int cnt=0; AM23XX_OUT_SET;//IO设置为输出 AM23XX_OUT(0); //主机发开始信号, 单总线拉低(至少500us) delay_ms(1); AM23XX_OUT(1);//释放总线, 等待从机响应 delay_us(30);//延时(20~40us) AM23XX_IN_SET;//IO设置为输入 if(AM23XX_IN == 0)//检测从机响应信号 { cnt = 0; while(! AM23XX_IN)//等待低电平结束(80us) { = 100000) return 0; } cnt = 0; while(AM23XX_IN)//等待高电平结束 { = 100000) return 0; } for(i=0; i<5; i++) { AM_SensorData = AM23XX_Read_Byte(); } AM23XX_answerFlag = 1;//应答标志变量置位 } else { AM23XX_answerFlag = 0; } return AM23XX_answerFlag; } STM8S105版本: unsigned char Read_Temperature(void) //读温度 { unsigned char i; SET_OUT_STATUS; PB6(1); delay_us(10000); PB6(0); delay_us(600); asm("sim"); SET_IN_STATUS; EXTI_CR1 |= (1<<5)+(1<<4); //配置上下沿都可以 asm("rim"); RecvStatrFg=1; //开始接受标志位 RecvUselessBit=0; //第一个下降沿是没有意义的 RecvBytePot=0; //索引 RecvBit=0; //位索引 RecvTimeout =0; // 超时标志位 } 这个要与中断相联系。 #pragma vector = 7 //中断向量 __interrupt void PC_470Rx(void) { if(RecvStatrFg) { if(PC_IDR_IDR5==0)//下降沿 { RecvUselessBit++;//两者同时实现了i=i+1,但是++i返回值是i+1,而i++返回值是i. RecvTimeout=0; 1)//第一个下降沿不采用 { 2) { if(DataTime<10) { RecvData &= ~(1<<(7-RecvBit));//判断0 } else { RecvData |= (1<<(7-RecvBit)); //判断1 } RecvBit++; 7)//8位满清零 { RecvBytePot++; RecvBit=0; } } DataTime=0; } } } } C51版本和汇编版本在我发的附件里面 《AM2301(DHT21)规格书》里面 5,读数的话在《AM2301(DHT21)规格书》讲得很详细,还是上面的话,有问题大家一起探讨。 组合为:湿度高八位+湿度低八位+温度高八位+温度低八位+校验 6,效果照片展示 在示波器上的演示 明显看出 “1”与 “0” 3,在串口调试助手上的表示 在LCD(JLX12864G_086)上面的移植 关于JLX12864G_086的移植我在下一篇博客写写 最近在赶点东西哈 由于时间有限,有些混乱。大家要交流的可以联系我,很期待与大家的联系。转载请注明出处。
  • 热度 18
    2015-12-16 22:33
    3710 次阅读|
    3 个评论
    写在最前: 装载请注明出处,谢谢。 写在之前: 写博客的目的是为了记录自己的一些工作生活,其中可能有些由于本人水平有限而说的不对或者不准确,也请各位不吝赐教。之前在STM32F1上的移植没有意识到留下照片, 现在就用当前的STM8S作为演示(好吧,其实是因为我懒得重新接线哈) 上一篇:https://mbb.eet-china.com/blog/1850657-370272.html 我分享的附件清单如下,待有空再详细补足。 1.JLX12864G-086-PC的中文字库编程说明书 里面有C51的例程 2,LCD显示 在STM32上的显示 3,《JLX12864G-086》 里面有JLX12864G-086的指令。JLX12864G-086中有一些数字有着其特定的意义,当他作为命令发送时候,代表一条指令,作为数字时候就是普通的数据。 4,《JLX12864G-1016中文说明书》 JLX12864G-1016中文说明书.pdf是一本参考资料,对JLX12864G-086的学习很有意义,里面也提供了C51的例程 平台: STM32F1 和STM8S105 软件:STLINK IAR for STM8 功能: 实现数字输入 汉字输入 和带参数输入 关于JLX12864G-086-PC的若干事 1,JLX12864G-086-PC 是一款比较优良的显示屏,能做很低的功耗,也比较容易上手。 2,JLX12864G-086-PC 容易编写,SPI时序。 3,JLX12864G-086-PC 扩展性高。 4,.... 就初始化做一些解析 void JLX12864G_086_GPIOIntI(void) { PC_DDR |= (1<<1)+(1<<2)+(1<<4)+(1<<7);//RST SCK SDA CS PC_CR1 |= (1<<1)+(1<<2)+(1<<4)+(1<<7); PC_CR2 &=~((1<<1)+(1<<2)+(1<<4)+(1<<7)); // PC_DDR &=~(1<<4); //PC7悬浮输入 SDO // PC_CR1 &=~(1<<4); // PC_CR2 &=~(1<<4); PE_DDR |= (1<<5); //RS PE_CR1 |= (1<<5); PE_CR2 &=~(1<<5); PB_DDR |= (1<<0)+(1<<1)+(1<<2); // sck cs# ROM_in PB_CR1 |= (1<<0)+(1<<1)+(1<<2); PB_CR2 &=~((1<<0)+(1<<1)+(1<<2)); PB_DDR &=~(1<<3); //Rom_out PB_CR1 |= (1<<3); PB_CR2 &=~ (1<<3); //不要中断上拉输入 上拉输入 } 初始化的重点: 1,选的引脚不能是特殊引脚,比如VSS VDD 串口等 新手常会犯这种错误 2,上拉输入和中断上拉输入是不同的,如果你配置了中断上拉输入而不做中断函数配置,会提示进入 UNEXPECT HANDLE(未预计错误) Tip: UNEXPECT HANDLE 的错误很多情况下是因为你初始化了中断然而并没有配置好 3, ROM_OUT引脚对应字符库芯片的输入引脚,ROM_IN引脚对应字符库芯片的输出引脚,所以ROM_OUT要配置成上拉输入 4,延时要准确,我在这里分享给大家两个在示波器上得到验证的演示函数,当然大家最好在示波器上验证一下,此外,该延时只是大概延时,误差多多少少会有的,切不可当作准确演示。 Tip:任何时序的延时都是非常重要的,如果程序运行不对,程序也没有问题的情况下,很可能是延时不够准确。 /***************************************************** //在16M晶振下,必须在16M的情况下 void delay_us( unsigned int time) { unsigned int x; 0;x--) { asm("nop"); //一个asm("nop")函数经过示波器测试代表100ns asm("nop"); asm("nop"); asm("nop"); asm("nop"); //一个asm("nop")函数经过示波器测试代表100ns } } void delay_ms(unsigned int time) { unsigned int i; while(time--) 0;i--) delay_us(1); } **********************************************************/ void JLX12864G_086_IntI(void) //初始化 { //RST=1; //delay_ms(1000); //CS=0; delay_ms(20); RST=0; delay_ms(5); RST=1; Send_OrderOrDate_To_LCD(0xE2, 1); delay_ms(5); Send_OrderOrDate_To_LCD(0x2c, 1);/*升压步聚1*/ delay_ms(5); Send_OrderOrDate_To_LCD(0x2e, 1);/*升压步聚2*/ delay_ms(5); Send_OrderOrDate_To_LCD(0x2f, 1);/*升压步聚3*/ delay_ms(5); Send_OrderOrDate_To_LCD(0x24, 1);/*粗调对比度,可设置范围20~27*/ Send_OrderOrDate_To_LCD(0x81, 1);/*微调对比度*/ Send_OrderOrDate_To_LCD(0x1a, 1);/*微调对比度的值,可设置范围0~63 1f*/ Send_OrderOrDate_To_LCD(0xa2, 1);/*1/9偏压比(bias)*/ Send_OrderOrDate_To_LCD(0xc8, 1);/*行扫描顺序:从上到下*/ Send_OrderOrDate_To_LCD(0xa0, 1);/*列扫描顺序:从左到右*/ Send_OrderOrDate_To_LCD(0x40, 1);/*起始行:从第一行开始*/ ClearScreen(); //清屏 Send_OrderOrDate_To_LCD(0xaf, 1);/*开显示*/ //delay_ms(20); //CS=1; } Tip:如上所述,JLX12864G-086-PC 中有些数字代表着一个命令,在这里我不做解析。大家如有兴趣,可自行查阅我分享的第三份和第四份参考资料。 那么你就要问了,那怎么区别命令和数字呢?这里给大家一个我写的函数 /***********************************************************************/ //** 发送命令或数据 void Send_OrderOrDate_To_LCD(unsigned char data,unsigned char OrderorDateFlag) //OrderorDateFlag 1 :命令 0:data { unsigned char i; //ROM_CS=1; //delay_ms(10); CS=0; if(OrderorDateFlag) RS=0; //区别在这里 else RS=1; //区别在这里 //SPI 时序 for(i=0;i<8;i++) { SCK = 0; //if(!OrderorDateFlag) delay_us(2); //少量延时 delay_us(2); //少量延时 if(data & 0x80) SDA=1; //输出 1 else SDA = 0 ; SCK = 1; delay_us(2); //少量延时 data = data << 1; } } /***********************************************************************/ /***********************************************************************/ // 指定行和列写入 void LCDAddr(unsigned char page,unsigned char column) // { CS=0; column--; page--; Send_OrderOrDate_To_LCD(0xb0+page,1); 4)&0x0f)+0x10,1); Send_OrderOrDate_To_LCD(column&0x0f,1); } Tip; 要有间隔 如; DisplayWithParameter(1,10,"WenDu:",WenDu); DisplayWithParameter(3,10,"ShiDu:",ShiDu); 其中 “1”和 “3”是行 如果显示一半,很可能是你的传输数据时候 “i++”的问题 /***********************************************************************/ /***********************************************************************/ //带参数显示 void DisplayWithParameter(unsigned short page,unsigned short column,unsigned char *text,unsigned char data) { unsigned short i=0,j,m,k,n; static unsigned char data1 ; data1 = data; CS=0; 0x00) { =0x20)&&(text <=0x7e)) { j=text -0x20; for(n=0;n<2;n++) { LCDAddr(page+n,column); for(k=0;k<8;k++) { Send_OrderOrDate_To_LCD(ascii_table_8x16 ,0); } } i++; column+=8; } else { i++; } } 0x00) { i=n=k=0; j = data1 /10; //求出data 与0的十位 m = data1 % 10; // 个位 //j = 1; //m = 2; 9) j+=6; // j=data / 10; //求出data 与0的绝对值 for(n=0;n<2;n++) { if(j) { LCDAddr(page+n,column+2); for(k=0;k<8;k++) { Send_OrderOrDate_To_LCD(ascii_table_8x16 ,0); //column += 8; } } LCDAddr(page+n,column+10); for(k=0;k<8;k++) { Send_OrderOrDate_To_LCD(ascii_table_8x16 ,0); } } i++; column+=8; } CS=1; } /***********************************************************************/ /***********************************************************************/ //输出中文 ulong fontaddr=0; void display_GB2312_string(uchar page,uchar column,uchar *text) { uchar i= 0; 0x00)) { =0xb0) &&(text =0xa1)) { //国标简体(GB2312)汉字在晶联讯字库 IC 中的地址由以下公式来计算: //Address = ((MSB - 0xB0) * 94 + (LSB - 0xA1)+ 846)*32+ BaseAdd;BaseAdd=0 //由于担心 8 位单片机有乘法溢出问题,所以分三部取地址 fontaddr = (text - 0xb0)*94; fontaddr += (text -0xa1)+846; fontaddr = (ulong)(fontaddr*32); get_and_write_16x16(fontaddr,page,column); //从指定地址读出数据写到液晶屏指定(page,column)座标中 //get_and_write_5x8(fontaddr,page,column); //从指定地址读出数据写到液晶屏指定(page,column)座标中 i+=2; column+=16; } =0xa1) &&(text =0xa1)) { //国标简体(GB2312)15x16 点的字符在晶联讯字库 IC 中的地址由以下公式来计算: //Address = ((MSB - 0xa1) * 94 + (LSB - 0xA1))*32+ BaseAdd;BaseAdd=0 //由于担心 8 位单片机有乘法溢出问题,所以分三部取地址 fontaddr = (text - 0xa1)*94; fontaddr += (text -0xa1); fontaddr = (ulong)(fontaddr*32); get_and_write_16x16(fontaddr,page,column); //从指定地址读出数据写到液晶屏指定(page,column)座标中 //get_and_write_5x8(fontaddr,page,column); //从指定地址读出数据写到液晶屏指定(page,column)座标中 i+=2; column+=16; } =0x20) &&(text <=0x7e)) { fontaddr = (text - 0x20); fontaddr = (unsigned long)(fontaddr*16); fontaddr = (unsigned long)(fontaddr+0x3cf80); get_and_write_8x16(fontaddr,page,column); //从指定地址读出数据写到液晶屏指定(page,column)座标中 //get_and_write_8x16(fontaddr,page,column); //从指定地址读出数据写到液晶屏指定(page,column)座标中 i+=1; column+=8; } else i++; } } /***********************************************************************/ 好了,函数的解析就到这里,谢谢大家。以上函数都经过测试,没有问题。