当前位置: 首页 > news >正文

使用USI作为主SPI接口

代码;

lcd_drive.c

//*****************************************************************************
//
//  File........: LCD_driver.c
//
//  Author(s)...: ATMEL Norway
//
//  Target(s)...: ATmega169
//
//  Compiler....: AVR-GCC 3.3.1; avr-libc 1.0
//
//  Description.: Functions used to control the AVR Butterfly LCD
//
//  Revisions...: 1.0
//
//  YYYYMMDD - VER. - COMMENT                                       - SIGN.
//
//  20021015 - 1.0  - Written for STK502                            - JLL
//  20030116 - 2.0  - Code adapted to AVR Butterfly                 - KS
//  20031009          port to avr-gcc/avr-libc                      - M.Thomas
//
//*****************************************************************************#define REDUCED// Include files.
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <inttypes.h>
#include <avr/interrupt.h>
#include <avr/interrupt.h>// mt - for gButtonTimeout
// #include "button.h"#include "LCD_driver.h"#ifndef BOOL
#define BOOL    char
#define FALSE   0
#define TRUE    (!FALSE)
#endif// Variable from "button.c" to prevent button-bouncing
extern unsigned char gButtonTimeout;    volatile char gAutoPressJoystick = FALSE;// Used to indicate when the LCD interrupt handler should update the LCD
// mt jw char gLCD_Update_Required = FALSE;
volatile char gLCD_Update_Required = FALSE;// LCD display buffer (for double buffering).
volatile char LCD_Data[LCD_REGISTER_COUNT];// Buffer that contains the text to be displayed
// Note: Bit 7 indicates that this character is flashing
volatile char gTextBuffer[TEXTBUFFER_SIZE];// Only six letters can be shown on the LCD.
// With the gScroll and gScrollMode variables,
// one can select which part of the buffer to show
volatile signed char gScroll;
volatile char gScrollMode;Start-up delay before scrolling a string over the LCD
char gLCD_Start_Scroll_Timer = 0;// The gFlashTimer is used to determine the on/off
// timing of flashing characters
volatile char gFlashTimer = 0;// Turns on/off the colons on the LCD
char gColon = 0;// Look-up table used when converting ASCII to
// LCD display data (segment control)
// mt __flash unsigned int LCD_character_table[] =
unsigned int LCD_character_table[] PROGMEM =
{0x0A51,     // '*' (?)0x2A80,     // '+'0x0000,     // ',' (Not defined)0x0A00,     // '-'0x0A51,     // '.' Degree sign0x0000,     // '/' (Not defined)0x5559,     // '0'0x0118,     // '1'0x1e11,     // '20x1b11,     // '30x0b50,     // '40x1b41,     // '50x1f41,     // '60x0111,     // '70x1f51,     // '80x1b51,     // '9'0x0000,     // ':' (Not defined)0x0000,     // ';' (Not defined)0x0000,     // '<' (Not defined)0x0000,     // '=' (Not defined)0x0000,     // '>' (Not defined)0x0000,     // '?' (Not defined)0x0000,     // '@' (Not defined)0x0f51,     // 'A' (+ 'a')0x3991,     // 'B' (+ 'b')0x1441,     // 'C' (+ 'c')0x3191,     // 'D' (+ 'd')0x1e41,     // 'E' (+ 'e')0x0e41,     // 'F' (+ 'f')0x1d41,     // 'G' (+ 'g')0x0f50,     // 'H' (+ 'h')0x2080,     // 'I' (+ 'i')0x1510,     // 'J' (+ 'j')0x8648,     // 'K' (+ 'k')0x1440,     // 'L' (+ 'l')0x0578,     // 'M' (+ 'm')0x8570,     // 'N' (+ 'n')0x1551,     // 'O' (+ 'o')0x0e51,     // 'P' (+ 'p')0x9551,     // 'Q' (+ 'q')0x8e51,     // 'R' (+ 'r')0x9021,     // 'S' (+ 's')0x2081,     // 'T' (+ 't')0x1550,     // 'U' (+ 'u')0x4448,     // 'V' (+ 'v')0xc550,     // 'W' (+ 'w')0xc028,     // 'X' (+ 'x')0x2028,     // 'Y' (+ 'y')0x5009,     // 'Z' (+ 'z')0x0000,     // '[' (Not defined)0x0000,     // '\' (Not defined)0x0000,     // ']' (Not defined)0x0000,     // '^' (Not defined)0x0000      // '_'
};/*****************************************************************************
*
*   Function name : LCD_Init
*
*   Returns :       None
*
*   Parameters :    None
*
*   Purpose :       Initialize LCD_displayData buffer.
*                   Set up the LCD (timing, contrast, etc.)
*
*****************************************************************************/
void LCD_Init (void)
{LCD_AllSegments(FALSE);                     // Clear segment buffer.LCD_CONTRAST_LEVEL(LCD_INITIAL_CONTRAST);    //Set the LCD contrast level// Select asynchronous clock source, enable all COM pins and enable all// segment pins.LCDCRB = (1<<LCDCS) | (3<<LCDMUX0) | (7<<LCDPM0);// Set LCD prescaler to give a framerate of 32,0 HzLCDFRR = (0<<LCDPS0) | (7<<LCDCD0);    LCDCRA = (1<<LCDEN) | (1<<LCDAB);           // Enable LCD and set low power waveform//Enable LCD start of frame interruptLCDCRA |= (1<<LCDIE);gLCD_Update_Required = FALSE;}/*****************************************************************************
*
*   Function name : LCD_WriteDigit(char c, char digit)
*
*   Returns :       None
*
*   Parameters :    Inputs
*                   c: The symbol to be displayed in a LCD digit
*                   digit: In which digit (0-5) the symbol should be displayed
*                   Note: Digit 0 is the first used digit on the LCD,
*                   i.e LCD digit 2
*
*   Purpose :       Stores LCD control data in the LCD_displayData buffer.
*                   (The LCD_displayData is latched in the LCD_SOF interrupt.)
*
*****************************************************************************/
void LCD_WriteDigit(char c, char digit)
{unsigned int seg = 0x0000;                  // Holds the segment patternchar mask, nibble;volatile char *ptr;char i;if (digit > 5)                              // Skip if digit is illegalreturn;//Lookup character table for segmet dataif ((c >= '*') && (c <= 'z')){// c is a letterif (c >= 'a')                           // Convert to upper casec &= ~0x20;                         // if necessarryc -= '*';//mt seg = LCD_character_table[c];seg = (unsigned int) pgm_read_word(&LCD_character_table[(uint8_t)c]); }// Adjust mask according to LCD segment mappingif (digit & 0x01)mask = 0x0F;                // Digit 1, 3, 5elsemask = 0xF0;                // Digit 0, 2, 4ptr = LCD_Data + (digit >> 1);  // digit = {0,0,1,1,2,2}for (i = 0; i < 4; i++){nibble = seg & 0x000F;seg >>= 4;if (digit & 0x01)nibble <<= 4;*ptr = (*ptr & mask) | nibble;ptr += 5;}
}/*****************************************************************************
*
*   Function name : LCD_AllSegments(unsigned char input)
*
*   Returns :       None
*
*   Parameters :    show -  [TRUE;FALSE]
*
*   Purpose :       shows or hide all all LCD segments on the LCD
*
*****************************************************************************/
void LCD_AllSegments(char show)
{unsigned char i;if (show)show = 0xFF;// Set/clear all bits in all LCD registersfor (i=0; i < LCD_REGISTER_COUNT; i++)*(LCD_Data + i) = show;
}/*****************************************************************************
*
*   LCD Interrupt Routine
*
*   Returns :       None
*
*   Parameters :    None
*
*   Purpose: Latch the LCD_displayData and Set LCD_status.updateComplete
*
*****************************************************************************/SIGNAL(SIG_LCD)
{static char LCD_timer = LCD_TIMER_SEED;char c;char c_flash;char flash;char EOL;unsigned char i;#ifndef REDUCEDstatic char timeout_count;static char auto_joystick_count;
#endifc_flash=0; // mt#ifndef REDUCED
/**************** Button timeout for the button.c, START ****************/if(!gButtonTimeout){timeout_count++;if(timeout_count > 3){gButtonTimeout = TRUE;timeout_count = 0;}}/**************** Button timeout for the button.c, END ******************//**************** Auto press joystick for the main.c, START *************/if(gAutoPressJoystick == AUTO){auto_joystick_count++;if(auto_joystick_count > 16){gAutoPressJoystick = TRUE;auto_joystick_count = 15;}}elseauto_joystick_count = 0;/**************** Auto press joystick for the main.c, END ***************/    
#endifLCD_timer--;                    // Decreased every LCD frameif (gScrollMode){// If we are in scroll mode, and the timer has expired,// we will update the LCDif (LCD_timer == 0){if (gLCD_Start_Scroll_Timer == 0){gLCD_Update_Required = TRUE;}elsegLCD_Start_Scroll_Timer--;}}else    {   // if not scrolling,// disble LCD start of frame interrupt
//        cbi(LCDCRA, LCDIE);   //DEBUGgScroll = 0;}EOL = FALSE;if (gLCD_Update_Required == TRUE){// Duty cycle of flashing charactersif (gFlashTimer < (LCD_FLASH_SEED >> 1))flash = 0;elseflash = 1;// Repeat for the six LCD charactersfor (i = 0; i < 6; i++){if ((gScroll+i) >= 0 && (!EOL)){// We have some visible charactersc = gTextBuffer[i + gScroll];c_flash = c & 0x80 ? 1 : 0;c = c & 0x7F;if (c == '\0')EOL = i+1;      // End of character data}elsec = ' ';// Check if this character is flashingif (c_flash && flash)LCD_WriteDigit(' ', i);elseLCD_WriteDigit(c, i);}// Copy the segment buffer to the real segmentsfor (i = 0; i < LCD_REGISTER_COUNT; i++)*(pLCDREG + i) = *(LCD_Data+i);// Handle colonif (gColon)*(pLCDREG + 8) = 0x01;else*(pLCDREG + 8) = 0x00;// If the text scrolled off the display,// we have to start over again.if (EOL == 1)gScroll = -6;elsegScroll++;// No need to update anymoregLCD_Update_Required = FALSE;}// LCD_timer is used when scrolling textif (LCD_timer == 0){
/*        if ((gScroll <= 0) || EOL)LCD_timer = LCD_TIMER_SEED/2;else*/LCD_timer = LCD_TIMER_SEED;}// gFlashTimer is used when flashing charactersif (gFlashTimer == LCD_FLASH_SEED)gFlashTimer= 0;elsegFlashTimer++;}

lcd_functions.c

//*****************************************************************************
//
//  File........: LCD_functions.c
//
//  Author(s)...: ATMEL Norway
//
//  Target(s)...: ATmega169
//
//  Compiler....: AVR-GCC 3.3.1; avr-libc 1.0
//
//  Description.: Additional LCD functions, scrolling text and write data
//
//  Revisions...: 1.0
//
//  YYYYMMDD - VER. - COMMENT                                       - SIGN.
//
//  20021015 - 1.0  - Created                                       - LHM
//  20030116 - 2.0  - Code adapted to AVR Butterflyup               - KS
//  20031009          port to avr-gcc/avr-libc                      - M.Thomas
//
//*****************************************************************************#define REDUCED//  Include files
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <inttypes.h>
#include "LCD_driver.h"
#include "LCD_functions.h"#ifndef REDUCED
#include "BCD.h"
// mt only for KEY_* and ST_OPTIONS_DISPLAY* definitions:
#include "main.h"
#endif#define FALSE   0
#define TRUE    (!FALSE)// mt char CONTRAST = LCD_INITIAL_CONTRAST;
uint8_t CONTRAST = LCD_INITIAL_CONTRAST;// Start-up delay before scrolling a string over the LCD. "LCD_driver.c"
extern char gLCD_Start_Scroll_Timer;/****************************************************************************
*
*	Function name : LCD_puts_f
*
*	Returns :		None
*
*	Parameters :	pFlashStr: Pointer to the string in flash
*                   scrollmode: Not in use
*
*	Purpose :		Writes a string stored in flash to the LCD
*
*****************************************************************************/// mt void LCD_puts_f(char __flash *pFlashStr, char scrollmode)
void LCD_puts_f(const char *pFlashStr, char scrollmode)
{// char i;uint8_t i;while (gLCD_Update_Required);      // Wait for access to buffer// mt: for (i = 0; pFlashStr[i] && i < TEXTBUFFER_SIZE; i++)for (i = 0; (const char)(pgm_read_byte(&pFlashStr[i])) && i < TEXTBUFFER_SIZE; i++){// mt: gTextBuffer[i] = pFlashStr[i];gTextBuffer[i] = pgm_read_byte(&pFlashStr[i]);}gTextBuffer[i] = '\0';if (i > 6){gScrollMode = 1;        // Scroll if text is longer than display sizegScroll = 0;gLCD_Start_Scroll_Timer = 3;    //Start-up delay before scrolling the text}else{gScrollMode = 0;        gScroll = 0;}gLCD_Update_Required = 1;
}/****************************************************************************
*
*	Function name : LCD_puts
*
*	Returns :		None
*
*	Parameters :	pStr: Pointer to the string
*                   scrollmode: Not in use
*
*	Purpose :		Writes a string to the LCD
*
*****************************************************************************/
void LCD_puts(char *pStr, char scrollmode)
{uint8_t i; // char i;while (gLCD_Update_Required);      // Wait for access to bufferfor (i = 0; pStr[i] && i < TEXTBUFFER_SIZE; i++){gTextBuffer[i] = pStr[i];}gTextBuffer[i] = '\0';if (i > 6){gScrollMode = 1;        // Scroll if text is longer than display sizegScroll = 0;gLCD_Start_Scroll_Timer = 3;    //Start-up delay before scrolling the text}else{gScrollMode = 0;        gScroll = 0;}gLCD_Update_Required = 1;
}/****************************************************************************
*
*	Function name : LCD_putc
*
*	Returns :		None
*
*	Parameters :	digit: Which digit to write on the LCD
*                   character: Character to write
*
*	Purpose :		Writes a character to the LCD
*
*****************************************************************************/
// mt void LCD_putc(char digit, char character)
void LCD_putc(uint8_t digit, char character)
{if (digit < TEXTBUFFER_SIZE)gTextBuffer[digit] = character;
}/****************************************************************************
*
*	Function name : LCD_Clear
*
*	Returns :		None
*
*	Parameters :	None
*
*	Purpose :		Clear the LCD
*
*****************************************************************************/
void LCD_Clear(void)
{uint8_t i; // char i;for (i=0; i<TEXTBUFFER_SIZE; i++)gTextBuffer[i] = ' ';
}/****************************************************************************
*
*	Function name : LCD_Colon
*
*	Returns :		None
*
*	Parameters :	show: Enables the colon if TRUE, disable if FALSE
*
*	Purpose :		Enable/disable colons on the LCD
*
*****************************************************************************/
void LCD_Colon(char show)
{gColon = show;
}/****************************************************************************
*
*	Function name : LCD_UpdateRequired
*
*	Returns :		None
*
*	Parameters :	update: TRUE/FALSE
*                   scrollmode: not in use
*
*	Purpose :		Tells the LCD that there is new data to be presented
*
*****************************************************************************/
void LCD_UpdateRequired(char update, char scrollmode)
{while (gLCD_Update_Required);gScrollMode = scrollmode;gScroll = 0;gLCD_Update_Required = update;
}/****************************************************************************
*
*	Function name : LCD_FlashReset
*
*	Returns :		None
*
*	Parameters :	None
*
*	Purpose :		This function resets the blinking cycle of a flashing digit
*
*****************************************************************************/
void LCD_FlashReset(void)
{gFlashTimer = 0;
}#ifndef REDUCED/****************************************************************************
*
*	Function name : SetContrast
*
*   Returns :       char ST_state (to the state-machine)
*
*   Parameters :    char input (from joystick)
*
*	Purpose :		Adjust the LCD contrast
*
*****************************************************************************/
char SetContrast(char input)
{static char enter = 1;char CH, CL;if (enter){LCD_Clear();enter = 0;}CH = CHAR2BCD2(CONTRAST);CL = (CH & 0x0F) + '0';CH = (CH >> 4) + '0';LCD_putc(0, 'C');LCD_putc(1, 'T');LCD_putc(2, 'R');LCD_putc(3, ' ');LCD_putc(4, CH);LCD_putc(5, CL);LCD_UpdateRequired(TRUE, 0);if (input == KEY_PLUS)CONTRAST++;else if (input == KEY_MINUS)CONTRAST--;if (CONTRAST == 255)CONTRAST = 0;if (CONTRAST > 15)CONTRAST = 15;LCD_CONTRAST_LEVEL(CONTRAST);if (input == KEY_ENTER){enter = 1;return ST_OPTIONS_DISPLAY_CONTRAST;}return ST_OPTIONS_DISPLAY_CONTRAST_FUNC;
}#endif
// REDUCED

mian.c

/*《AVR专题精选》随书例程3.通信接口使用技巧项目:使用USI作为主SPI接口文件:main.c说明:主程序文件. 在AVR Bufferfly上演示USI做主SPI接口用法控制EEPROM 25AA010按键: 上  数据加下  数据减左  读取数据右  写数据中  随机数据作者:邵子扬时间:2012年12月15日*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>
#include <stdio.h>// 系统时钟频率
#define F_CPU 1000000UL#include <util/delay.h>#include "LCD_functions.h"
#include "LCD_driver.h"#include "macromcu.h"// 定义端口
#define SS   B, 0
#define SCK  E, 4
#define MOSI E, 6
#define MISO E, 5// SPI初始化
void SPI_init()
{PINSET(SS);USIDR = 0;USISR = (1<<USIOIF);USICR = (1<<USIWM0)|(1<<USICLK)|(1<<USICLK);
}// SPI读写函数
unsigned char SPI_WR(unsigned char dat)
{unsigned char i;USIDR = dat; // 数据放入USI数据寄存器for(i = 0; i < 8; i++)  // 软件方式驱动时钟信号{USICR = (1<<USIWM0)|(1<<USITC);USICR = (1<<USIWM0)|(1<<USITC)|(1<<USICLK);}return USIDR; // 返回数据
}// 按键掩码
#define PINB_MASK ((1<<PINB4)|(1<<PINB6)|(1<<PINB7))
#define PINE_MASK ((1<<PINE2)|(1<<PINE3))// 读取按键状态
unsigned char getkey()
{unsigned char t;t = (~PINB) & PINB_MASK;t |= (~PINE) & PINE_MASK;return t;
}unsigned char dat = 0, cnt;
char s[] = "    00";// HEX数据转换为字符
unsigned char hexchr(unsigned char dat)
{if(dat > 15)return '0';if(dat < 10)return dat + '0';elsereturn dat - 10 + 'A';
}// HEX数据转换字符串
void hexbuf(unsigned char dat, char *buf)
{buf[0] = hexchr(dat/16);buf[1] = hexchr(dat%16);
}// 从EEPROM地址0读取一个字节
unsigned char ReadByte()
{unsigned char t;PINCLR(SS);    // 片选信号SPI_WR(0x03);  // 发读命令SPI_WR(0x00);  // 地址高位SPI_WR(0x00);  // 地址低位t = SPI_WR(0); // 数据PINSET(SS);    // 禁止片选return t;
}// 写入一个字节到EEPROM地址0
void WriteByte(unsigned char dat)
{PINCLR(SS);    // 使能片选SPI_WR(0x02);  // 发送写命令SPI_WR(0x00);  // 地址高位SPI_WR(0x00);  // 地址低位SPI_WR(dat);   // 数据PINSET(SS);    // 禁止片选
}// 允许写入EEPROM
void WREN(void)
{PINCLR(SS);    // 片选SPI_WR(0x06);  // 发送wren命令PINSET(SS);  
}// 主程序
int main()
{// IO 初始化PINDIR(SS,   PIN_OUTPUT);PINDIR(SCK,  PIN_OUTPUT);PINDIR(MOSI, PIN_OUTPUT);PINDIR(MISO, PIN_OUTPUT);PORTB |= PINB_MASK;PORTE |= PINE_MASK;// SPI初始化SPI_init(0, 0);// AVR Butterfly LCD初始化LCD_Init();// 开中断sei();// 显示地址和数据hexbuf(dat, s+4);LCD_puts(s, 0);while(1){_delay_ms(200);  // 延时cnt++;if(getkey())     // 读取按键{switch(getkey()){case 0x40://updat++;     // 数据递增s[0] = ' ';break;case 0x80://dndat--;     // 数据递减s[0] = ' ';break;case 0x04://lefts[0] = 'R';  // 左键代表读取数据dat = ReadByte();break;case 0x08://rights[0] = 'W';  // 右键写入数据WREN();WriteByte(dat);break;case 0x10://enter//dat = ReadStatus();//hexbuf(dat, s+2);dat = cnt;    // 回车键随机设置数据break;}hexbuf(dat, s+4);LCD_puts(s, 0);}}return 0;
}

仿真效果图:

http://www.lryc.cn/news/380014.html

相关文章:

  • AI播客下载:Eye on AI(AI深度洞察)
  • Flink 窗口触发器
  • Java面试题:解释线程间如何通过wait、notify和notifyAll方法进行通信
  • 【机器学习 复习】第9章 降维算法——PCA降维
  • Ubuntu系统docker gpu环境搭建
  • 网络安全-如何设计一个安全的API(安全角度)
  • 微积分-导数1(导数与变化率)
  • 最新PHP仿猪八戒任务威客网整站源码/在线接任务网站源码
  • Windows安装配置jdk和maven
  • 电子SOP实施(MQTT协议)
  • 【Unity导航系统】Navigation组件的概念及其使用示例
  • vue-cli 根据文字生成pdf格式文件 jsPDF
  • 【嵌入式DIY实例】-Nokia 5110显示DS3231 RTC数据
  • 【十三】图解mybatis缓存模块之装饰器模式
  • 字节大神强推千页PDF学习笔记,弱化学历问题,已拿意向书字节提前批移动端!
  • Python爬虫-贝壳二手房“改进版”
  • zookeeper学习、配置文件参数详解
  • SVG 模糊效果
  • Electron+vite+vuetify项目搭建
  • 洛谷:P1085 [NOIP2004 普及组] 不高兴的津津
  • Webpack4从入门到精通以及和webpack5对比_webpack现在用的是哪个版本
  • 巴鲁夫MacroBuilder2.0.0.0软件巴鲁夫和使用手侧
  • 分享:Javascript开源桌面环境-Puter
  • 【idea-jdk1.8】使用Spring Initializr 创建 Spring Boot项目没有JDK8
  • 647. 回文子串(leetcode)
  • 【车载开发系列】汽车嵌入式开发常用工具介绍
  • python脚本获取本机IP的方式
  • 查看LabVIEW及各个模块和驱动的版本号
  • LLM主流架构和模型
  • 为企业提供动力:用于大型组织的WordPress