资源描述
/stm32-12864并行驱动程序/#include delay.h/必须配合 delay.c 和 delay.h 文件使用,所以要包含 delay.h。#include display12864.hf/* 以下是相关引脚定义。*/ A 口的#defineDisIOGPIOE/定义 12864 要使用的 I/O 端口。#defineDisClkRCC_APB2Periph_GPIOE/定义 12864 要使用的 I/O 端口 的时钟。#defineData GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPI O_Pin_7/定义 12864 使用的数据引脚。#defineENGPIO_Pin_10/定义使能端使用的引脚/*/#defineDisIOIOGPIOE/定义 12864 要使用的 I/O 端口。#defineDisClkIORCC_APB2Periph_GPIOE/定义 12864 要使用的 I/O 端口的时钟。#defineRS#defineRWGPIO_Pin_9GPIO_Pin_8/*光标定位函数定义结束。*/#define x10x80#define x20x88#define y0x80GPIO_InitTypeDefGPIOStru;/定义用于定义所以引脚为输出的变量。/* 函数名: IOInitOut* 函数描述: 把所有端口初始化为推挽输出模式的函数* 输入参数: 无* 输出结果: 无* 返回值: 无*/void IOInitOut(void)/IO 组GPIOStru.GPIO_Mode=GPIO_Mode_Out_PP;/ 定 义 所 有 的 引 脚 为 推挽输出的变量初始化。GPIOStru.GPIO_Speed =GPIO_Speed_50MHz; GPIOStru.GPIO_Pin=Data| EN;RCC_APB2PeriphClockCmd(DisClkIO,ENABLE); GPIO_Init(DisIO,&GPIOStru);/IO 组GPIOStru.GPIO_Mode = GPIO_Mode_Out_PP;/ 定 义 所 有 的 引 脚 为 推挽输出的变量初始化。GPIOStru.GPIO_Speed = GPIO_Speed_50MHz; GPIOStru.GPIO_Pin =RS|RW;RCC_APB2PeriphClockCmd(DisClkIO,ENABLE); GPIO_Init(DisIO,&GPIOStru);/* 函数名: IOInitIn* 函数描述: 把数据引脚初始化为浮空输入的函* 输入参数: 无* 输出结果: 无* 返回值: 无*/void IOInitIn(void)GPIOStru.GPIO_Mode = GPIO_Mode_IN_FLOATING;/ 定义数据 引脚为浮空输 入的变量初始化。GPIOStru.GPIO_Speed = GPIO_Speed_50MHz; GPIOStru.GPIO_Pin = Data;RCC_APB2PeriphClockCmd(DisClkIO,ENABLE);/ 把 所 有 端 口 初 始 化 为输出模式的函数。GPIO_Init(DisIO,&GPIOStru);/* 函数名: WaitBusy* 函数描述: 等待 12864 的忙状态结束的函数* 输入参数: 无* 输出结果: 无* 返回值: 无*/void WaitBusy(void)IOInitIn();/ 把 数据引脚定义为浮空输入GPIO_ResetBits(DisIOIO,RS);/RS = 0GPIO_SetBits(DisIOIO,RW);/RW = 1.GPIO_SetBits(DisIO,EN);/EN = 1.while(GPIO_ReadInputData(DisIO) & 0x0080);/只要位 7 的值,位 7 是忙标志位GPIO_ResetBits(DisIO,EN);/EN = 0;IOInitOut();/把所有引脚定义为输出。/* 函数名: WriteCmd* 函数描述: 写命令函数* 输入参数: 8 位命令* 输出结果: 无* 返回值: 无*/void WriteCmd(uint8_t cmd)WaitBusy();GPIO_ResetBits(DisIOIO,RS);/RS = 0. GPIO_ResetBits(DisIOIO,RW);/RW = 0.GPIO_SetBits(DisIO,EN);/EN = 1.DisIO-ODR=(DisIO-ODR & 0xff00)|cmd);/此处,只有直接操作寄存器才能/达到,只改变输出数据寄存器 ODR 的低 8 位,其它位/不变的目的。因为,只有低 8 位是数据引脚,/其它位可能是控制引脚,不能改变。delay_us(2);GPIO_ResetBits(DisIO,EN);/EN = 0;delay_us(2);/* 函数名: WriteData* 函数描述: 写数据函数* 输入参数: 8 位命令* 输出结果: 无* 返回值: 无*/void WriteData(uint8_t data)WaitBusy();GPIO_SetBits(DisIOIO,RS);/RS = 1.GPIO_ResetBits(DisIOIO,RW);/RW = 0. GPIO_SetBits(DisIO,EN);/EN = 1.DisIO-ODR=(DisIO-ODR & 0xff00)|data);/同上。delay_us(2);GPIO_ResetBits(DisIO,EN);/EN = 0;delay_us(2);/* 函数名: ReadData* 函数描述: 读 IO 口状态* 输入参数: 无* 输出结果: 无* 返回值: 8 位数据*/uint8_t ReadData(void)uint8_t uc_Content; WaitBusy();IOInitIn();delay_ms(10);/注意:用 BCDE 组 IO 口必须这个延时!GPIO_SetBits(DisIOIO,RW);/RW = 1;读模式GPIO_SetBits(DisIOIO,RS);/RS = 1;数据GPIO_SetBits(DisIO,EN);/EN = 1.使能delay_us(2);/延时很重要/uc_Content = (DisIO-IDR)&0x00ff; uc_Content = GPIO_ReadInputData(DisIO);GPIO_ResetBits(DisIO,EN);/EN = 0.delay_us(2);/延时很重要IOInitOut();return uc_Content;/* 函数名: InitDis* 函数描述: 初始化 12864 和要用到的 STM 32 的引脚* 输入参数: 无* 输出结果: 无* 返回值: 无*/void InitDis(void)IOInitOut();delay_init(8);/初始化延时函数的微妙计数基数。WriteCmd(0x30);/选择基本指令集,和,8 位数据模式。 delay_ms(2);WriteCmd(0x0c);/开显示,无游标,不反白.delay_ms(2);WriteCmd(0x01);/清除显示,并将 DDRAM 的地址计数器 AC 设为 00H. delay_ms(2);WriteCmd(0x06);/设置,外部读写数据后,地址记数器 AC 会自动加 1。delay_ms(2);WriteCmd(0x80);/将 DDRAM 地址计数器 AC 设为 0. delay_ms(2);/* 函数名: DisStr* 函数描述: 显示字符串的函数* 输入参数: 字符串地址* 输出结果: 无* 返回值: 无*/void DisStr(uint8_t *s)while(*s != 0)WriteData(*s); s+;delay_ms(2);/* 函数名: DisInt* 函数描述: 显示整型变量的函数,最多显示 16 位的整数(只能显示正数)* 输入参数: 16 位二进制无符号整型数据* 输出结果: 无* 返回值: 无*/void DisInt(uint16_t num)数倍,uint8_t temp17; uint8_t str17; int i=0,j=0;while(num != 0)/这里不能用 num%10 != 0,如果 num 是 10 的整/例如,100,这样就会出错,根本就不能进入循环体。tempi = (num%10) + 0x30; num /= 10;i+;i-;/因为 i 在退出循环之前还自加了一次,此时,/ 指向最后一个存储有用值的元素的后一个位置。while(i != -1)/因为 i=0 时,temp0还是有用值。strj = tempi; j+;i-;strj = 0;/因为 i 在退出循环之前还自加了一次,此时,/ 指向最后一个存储有用值的元素的后一个位置。DisStr(str);/* 函数名: DisFloat* 函数描述: 显示有 n 位小数的浮点数,总位数不超过 16 位* 输入参数: 16 位数据* 输出结果: 无* 返回值: 无*/void DisFloat(int n,float fnum)long int num = fnum*10; uint8_t temp17; uint8_t str17;int i=0,j=0; while(num != 0)tempi = (num%10)+0x30; num/=10;i+;if(i = n)/4 位小数处理完后,加入小数点。 i-;tempi = .; i+;while(i != -1)strj = tempi; j+;i-;strj=0; DisStr(str);/* 函数名: Locate16* 函数描述: 光标定位函数, 第一个参数为行坐标, 第二个为列坐标,起始坐标是 1 行 1 列, 只能以 16 个点的宽度为单位移动* 输入参数: row - 行, col - 列* 输出结果: 无* 返回值: 无*/void Locate16(int row, int col)switch(row)case 1: WriteCmd(0x80+col-1); break; case 2: WriteCmd(0x90+col-1); break; case 3: WriteCmd(0x88+col-1); break; case 4: WriteCmd(0x98+col-1); break;/显示绘图 全屏/* 函数名: DisInt* 函数描述: 显示有 1 位小数的浮点数,总位数不超过 16 位* 输入参数: 数据* 输出结果: 无* 返回值: 无*/void ImageWhole(uint8_t *img)uint8_t i,j; for(j=0;j32;j+)/上半屏for(i=0;i8;i+)WriteCmd(0x34);WriteCmd(y+j);/给命令给第几行垂直坐标 WriteCmd(x1+i);/给命令给第几列水平坐标 WriteCmd(0x30);WriteData(imgj*16+i*2); WriteData(imgj*16+i*2+1);for(j=32;j64;j+)/下半屏for(i=0;i8;i+)WriteCmd(0x34);/关闭绘图WriteCmd(y+j-32);/给命令给第几行垂直坐标 WriteCmd(x2+i);/给命令给第几列水平坐标 WriteCmd(0x30);WriteData(imgj*16+i*2); WriteData(imgj*16+i*2+1);WriteCmd(0x36);/打开绘图/* 函数名: DrawPoint* 函数描述: 画点函数* 输入参数: xx - 行, yy - 列 (x, y)* 输出结果: 无* 返回值: 无*/void DrawPoint(uint8_t xx,uint8_t yy)uint8_t x_byte, x_bit;/在横坐标的哪一个字节,哪一个位 uint8_t y_byte, y_bit;uint8_t tmph, tmpl;/定义两个临时变量,用于存放读出来的数据tmph=0; tmpl=0;xx = xx & 0x7F; yy = yy & 0x3F;x_byte = xx / 16;/算出它在哪一个字节(地址)注意一个地址是 16 位的x_bit = xx & 0x0F;/算出它在哪一个位y_byte = yy /32;/y 是没在哪个字节这个说法 这里只是确定它在上半屏还是下半屏上半屏 1:下半屏y_bit = yy & 0x1F;/y_bit 确定它是在第几行WriteCmd(0x34);/扩展指令集WriteCmd(0x34);/绘图显示关闭WriteCmd(0x80 + y_bit);/先写垂直地址(最高位必须为 1)具体参照数据手册WriteCmd(0x80 + x_byte + 8*y_byte);/水平坐标/下半屏的水平坐标起始地址为 0x88/(+8*y_byte)就是用来确定在上半屏还是下半屏ReadData();/先空读一次tmph = ReadData();/读高位tmpl = ReadData();/读低位WriteCmd(0x80 + y_bit);/读操作会改变 AC,所以重新设置一次 WriteCmd(0x80 + x_byte + 8*y_byte);/0:/if (x_bit 8)/如果 x_bit 位数小于 8WriteData(tmph|(0x01 (7 - x_bit);/写高字节。因为坐标是从左向右的/而 GDRAM 高位在左,底位在右WriteData(tmpl);/原数据送回elseWriteData(tmph);/原数据送回WriteData(tmpl | (0x01 (15 - x_bit);WriteCmd(0x36);/打开绘图显示WriteCmd(0x30);/回到基本指令集,毕竟 ST7920是以字符为主的/* 函数名: ClearPoint* 函数描述: 清除点函数* 输入参数: xx - 行, yy - 列 (x, y)* 输出结果: 无* 返回值: 无*/void ClearPoint(uint8_t xx,uint8_t yy)uint8_t x_byte, x_bit;/在横坐标的哪一个字节,哪一个位 uint8_t y_byte, y_bit;uint8_t tmph, tmpl;/定义两个临时变量,用于存放读出来的数据tmph=0; tmpl=0;xx = xx & 0x7F; yy = yy & 0x3F;x_byte = xx / 16;/算出它在哪一个字节(地址)注意一个地址是 16 位的x_bit = xx & 0x0F;/算出它在哪一个位y_byte = yy /32;/y 是没在哪个字节这个说法 这里只是确定它在上半屏还是下半屏上半屏 1:下半屏/0:y_bit = yy & 0x1F;/y_bit 确定它是在第几行WriteCmd(0x34);/扩展指令集WriteCmd(0x34);/绘图显示关闭WriteCmd(0x80 + y_bit);/先写垂直地址(最高位必须为 1)/具体参照数据手册WriteCmd(0x80 + x_byte + 8*y_byte); /水平坐标/下半屏的水平坐标起始地址为 0x88/(+8*y_byte)就是用来确定在上半屏还是下半屏ReadData();/先空读一次tmph = ReadData();/读高位tmpl = ReadData();/读低位WriteCmd(0x80 + y_bit);/读操作会改变 AC,所以重新设置一次 WriteCmd(0x80 + x_byte + 8*y_byte);if (x_bit 8)/如果 x_bit 位数小于 8WriteData(tmph&(0xfe (7 - x_bit);/写高字节。因为坐标是从左向右的右/而 GDRAM 高位在左,底位在WriteData(tmpl);/ 原 数据送回elseWriteData(tmph);/原数据送回WriteData(tmpl & (0xfe (15 - x_bit);WriteCmd(0x36);/打开绘图显示WriteCmd(0x30);/回到基本指令集,毕竟 ST7920是以字符为主的/* 函数名: ClearAll* 函数描述: 清整个 GDRAM 空间* 输入参数: 无* 输出结果: 无* 返回值: 无*/void ClearAll(void)uint8_t xxx, yyy; for(yyy=0; yyy64; yyy+)for(xxx=0; xxx xx1)temp = xx0; xx0 = xx1; xx1 = temp;for(xx0=xx0; xx0yy1)temp=yy0; yy0=yy1; yy1=temp;for(yy0=yy0;yy0=xx1* 输出结果: 无* 返回值: 无*/void DrawLine(uint8_t xx1,uint8_t yy1,uint8_t xx2,uint8_t yy2)uint8_t x_add,y_add,y_temp,Line_K;xx1&=0x7f;xx2&=0x7f;/去掉 128 倍yy1&=0x3f;yy2&=0x3f;/去掉 64 倍if(xx2xx1)if( yy2yy1 | yy2=yy1 )Line_K=(yy2-yy1)/(xx2-xx1); for(x_add=0;x_add=(xx2-xx1);x_add+)y_temp=yy1+(Line_K*(x_add+xx1); DrawPoint(x_add+xx1,y_temp);elseLine_K=(yy1-yy2)/(xx2-xx1);for(x_add=0;x_add=(xx2-xx1);x_add+)y_temp=yy1-(Line_K*(x_add+xx1); DrawPoint(x_add+x1,y_temp);else if(xx2=xx1)for(y_add=0;y_add 31 | r = 0 )/圆大于液晶屏或者没半径则返回 return;a = 0;b = r;di = 3 - 2 * r;/判断下个点位置的标志while(a = b)DrawPoint( x0 - b , y0 - a);/3DrawPoint( x0 + b , y0 - a);/0DrawPoint( x0 - a , y0 + b);/1DrawPoint( x0 - b , y0 - a);/7DrawPoint( x0 - a , y0 - b);/2DrawPoint( x0 + b , y0 + a);/4DrawPoint( x0 + a , y0 - b);/5DrawPoint( x0 + a , y0 + b);/6 DrawPoint( x0 - b , y0 + a);a +;/使用 bresenham 算法画圆if(di 0)di += 4 * a + 6;elsedi += 10 + 4 * (a - b); b -;DrawPoint( x0 + a , y0 + b);
展开阅读全文